rax86.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. Handles the common x86 assembler reader routines
  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. {
  19. Contains the common x86 (i386 and x86-64) assembler reader routines.
  20. }
  21. unit rax86;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. aasmbase,aasmtai,aasmcpu,
  26. cpubase,rautils,cclasses;
  27. { Parser helpers }
  28. function is_prefix(t:tasmop):boolean;
  29. function is_override(t:tasmop):boolean;
  30. Function CheckPrefix(prefixop,op:tasmop): Boolean;
  31. Function CheckOverride(overrideop,op:tasmop): Boolean;
  32. Procedure FWaitWarning;
  33. type
  34. T386Operand=class(TOperand)
  35. Procedure SetCorrectSize(opcode:tasmop);override;
  36. end;
  37. T386Instruction=class(TInstruction)
  38. OpOrder : TOperandOrder;
  39. { Operand sizes }
  40. procedure AddReferenceSizes;
  41. procedure SetInstructionOpsize;
  42. procedure CheckOperandSizes;
  43. procedure CheckNonCommutativeOpcodes;
  44. procedure SwapOperands;
  45. { opcode adding }
  46. procedure ConcatInstruction(p : taasmoutput);override;
  47. end;
  48. tstr2opentry = class(Tnamedindexitem)
  49. op: TAsmOp;
  50. end;
  51. const
  52. AsmPrefixes = 6;
  53. AsmPrefix : array[0..AsmPrefixes-1] of TasmOP =(
  54. A_LOCK,A_REP,A_REPE,A_REPNE,A_REPNZ,A_REPZ
  55. );
  56. AsmOverrides = 6;
  57. AsmOverride : array[0..AsmOverrides-1] of TasmOP =(
  58. A_SEGCS,A_SEGES,A_SEGDS,A_SEGFS,A_SEGGS,A_SEGSS
  59. );
  60. CondAsmOps=3;
  61. CondAsmOp:array[0..CondAsmOps-1] of TasmOp=(
  62. A_CMOVcc, A_Jcc, A_SETcc
  63. );
  64. CondAsmOpStr:array[0..CondAsmOps-1] of string[4]=(
  65. 'CMOV','J','SET'
  66. );
  67. implementation
  68. uses
  69. globtype,globals,systems,verbose,
  70. cpuinfo,agx86att;
  71. {$define ATTOP}
  72. {$define INTELOP}
  73. {$ifdef NORA386INT}
  74. {$ifdef NOAG386NSM}
  75. {$ifdef NOAG386INT}
  76. {$undef INTELOP}
  77. {$endif}
  78. {$endif}
  79. {$endif}
  80. {$ifdef NORA386ATT}
  81. {$ifdef NOAG386ATT}
  82. {$undef ATTOP}
  83. {$endif}
  84. {$endif}
  85. {*****************************************************************************
  86. Parser Helpers
  87. *****************************************************************************}
  88. function is_prefix(t:tasmop):boolean;
  89. var
  90. i : longint;
  91. Begin
  92. is_prefix:=false;
  93. for i:=1 to AsmPrefixes do
  94. if t=AsmPrefix[i-1] then
  95. begin
  96. is_prefix:=true;
  97. exit;
  98. end;
  99. end;
  100. function is_override(t:tasmop):boolean;
  101. var
  102. i : longint;
  103. Begin
  104. is_override:=false;
  105. for i:=1 to AsmOverrides do
  106. if t=AsmOverride[i-1] then
  107. begin
  108. is_override:=true;
  109. exit;
  110. end;
  111. end;
  112. Function CheckPrefix(prefixop,op:tasmop): Boolean;
  113. { Checks if the prefix is valid with the following opcode }
  114. { return false if not, otherwise true }
  115. Begin
  116. CheckPrefix := TRUE;
  117. (* Case prefix of
  118. A_REP,A_REPNE,A_REPE:
  119. Case opcode Of
  120. A_SCASB,A_SCASW,A_SCASD,
  121. A_INS,A_OUTS,A_MOVS,A_CMPS,A_LODS,A_STOS:;
  122. Else
  123. Begin
  124. CheckPrefix := FALSE;
  125. exit;
  126. end;
  127. end; { case }
  128. A_LOCK:
  129. Case opcode Of
  130. A_BT,A_BTS,A_BTR,A_BTC,A_XCHG,A_ADD,A_OR,A_ADC,A_SBB,A_AND,A_SUB,
  131. A_XOR,A_NOT,A_NEG,A_INC,A_DEC:;
  132. Else
  133. Begin
  134. CheckPrefix := FALSE;
  135. Exit;
  136. end;
  137. end; { case }
  138. A_NONE: exit; { no prefix here }
  139. else
  140. CheckPrefix := FALSE;
  141. end; { end case } *)
  142. end;
  143. Function CheckOverride(overrideop,op:tasmop): Boolean;
  144. { Check if the override is valid, and if so then }
  145. { update the instr variable accordingly. }
  146. Begin
  147. CheckOverride := true;
  148. { Case instr.getinstruction of
  149. A_MOVS,A_XLAT,A_CMPS:
  150. Begin
  151. CheckOverride := TRUE;
  152. Message(assem_e_segment_override_not_supported);
  153. end
  154. end }
  155. end;
  156. Procedure FWaitWarning;
  157. begin
  158. if (target_info.system=system_i386_GO32V2) and (cs_fp_emulation in aktmoduleswitches) then
  159. Message(asmr_w_fwait_emu_prob);
  160. end;
  161. {*****************************************************************************
  162. T386Operand
  163. *****************************************************************************}
  164. Procedure T386Operand.SetCorrectSize(opcode:tasmop);
  165. begin
  166. if gas_needsuffix[opcode]=attsufFPU then
  167. begin
  168. case size of
  169. S_L : size:=S_FS;
  170. S_IQ : size:=S_FL;
  171. end;
  172. end
  173. else if gas_needsuffix[opcode]=attsufFPUint then
  174. begin
  175. case size of
  176. S_W : size:=S_IS;
  177. S_L : size:=S_IL;
  178. end;
  179. end;
  180. end;
  181. {*****************************************************************************
  182. T386Instruction
  183. *****************************************************************************}
  184. procedure T386Instruction.SwapOperands;
  185. begin
  186. Inherited SwapOperands;
  187. { mark the correct order }
  188. if OpOrder=op_intel then
  189. OpOrder:=op_att
  190. else
  191. OpOrder:=op_intel;
  192. end;
  193. procedure T386Instruction.AddReferenceSizes;
  194. { this will add the sizes for references like [esi] which do not
  195. have the size set yet, it will take only the size if the other
  196. operand is a register }
  197. var
  198. operand2,i : longint;
  199. s : tasmsymbol;
  200. so : longint;
  201. begin
  202. for i:=1to ops do
  203. begin
  204. operands[i].SetCorrectSize(opcode);
  205. if (operands[i].size=S_NO) then
  206. begin
  207. case operands[i].Opr.Typ of
  208. OPR_REFERENCE :
  209. begin
  210. if i=2 then
  211. operand2:=1
  212. else
  213. operand2:=2;
  214. if operand2<ops then
  215. begin
  216. { Only allow register as operand to take the size from }
  217. if operands[operand2].opr.typ=OPR_REGISTER then
  218. begin
  219. if ((opcode<>A_MOVD) and
  220. (opcode<>A_CVTSI2SS)) then
  221. operands[i].size:=operands[operand2].size;
  222. end
  223. else
  224. begin
  225. { if no register then take the opsize (which is available with ATT),
  226. if not availble then give an error }
  227. if opsize<>S_NO then
  228. operands[i].size:=opsize
  229. else
  230. begin
  231. Message(asmr_e_unable_to_determine_reference_size);
  232. { recovery }
  233. operands[i].size:=S_L;
  234. end;
  235. end;
  236. end
  237. else
  238. begin
  239. if opsize<>S_NO then
  240. operands[i].size:=opsize
  241. end;
  242. end;
  243. OPR_SYMBOL :
  244. begin
  245. { Fix lea which need a reference }
  246. if opcode=A_LEA then
  247. begin
  248. s:=operands[i].opr.symbol;
  249. so:=operands[i].opr.symofs;
  250. operands[i].opr.typ:=OPR_REFERENCE;
  251. Fillchar(operands[i].opr.ref,sizeof(treference),0);
  252. operands[i].opr.ref.symbol:=s;
  253. operands[i].opr.ref.offset:=so;
  254. end;
  255. operands[i].size:=S_L;
  256. end;
  257. end;
  258. end;
  259. end;
  260. end;
  261. procedure T386Instruction.SetInstructionOpsize;
  262. begin
  263. if opsize<>S_NO then
  264. exit;
  265. if (OpOrder=op_intel) then
  266. SwapOperands;
  267. case ops of
  268. 0 : ;
  269. 1 :
  270. { "push es" must be stored as a long PM }
  271. if ((opcode=A_PUSH) or
  272. (opcode=A_POP)) and
  273. (operands[1].opr.typ=OPR_REGISTER) and
  274. ((operands[1].opr.reg.enum in [firstsreg..lastsreg]) or
  275. ((operands[1].opr.reg.enum=R_INTREGISTER) and
  276. (operands[1].opr.reg.number>=nfirstsreg) and
  277. (operands[1].opr.reg.number<=nlastsreg))) then
  278. opsize:=S_L
  279. else
  280. opsize:=operands[1].size;
  281. 2 :
  282. begin
  283. case opcode of
  284. A_MOVZX,A_MOVSX :
  285. begin
  286. case operands[1].size of
  287. S_W :
  288. case operands[2].size of
  289. S_L :
  290. opsize:=S_WL;
  291. end;
  292. S_B :
  293. case operands[2].size of
  294. S_W :
  295. opsize:=S_BW;
  296. S_L :
  297. opsize:=S_BL;
  298. end;
  299. end;
  300. end;
  301. A_MOVD : { movd is a move from a mmx register to a
  302. 32 bit register or memory, so no opsize is correct here PM }
  303. exit;
  304. A_OUT :
  305. opsize:=operands[1].size;
  306. else
  307. opsize:=operands[2].size;
  308. end;
  309. end;
  310. 3 :
  311. opsize:=operands[3].size;
  312. end;
  313. end;
  314. procedure T386Instruction.CheckOperandSizes;
  315. var
  316. sizeerr : boolean;
  317. i : longint;
  318. begin
  319. { Check only the most common opcodes here, the others are done in
  320. the assembler pass }
  321. case opcode of
  322. A_PUSH,A_POP,A_DEC,A_INC,A_NOT,A_NEG,
  323. A_CMP,A_MOV,
  324. A_ADD,A_SUB,A_ADC,A_SBB,
  325. A_AND,A_OR,A_TEST,A_XOR: ;
  326. else
  327. exit;
  328. end;
  329. { Handle the BW,BL,WL separatly }
  330. sizeerr:=false;
  331. { special push/pop selector case }
  332. if ((opcode=A_PUSH) or
  333. (opcode=A_POP)) and
  334. (operands[1].opr.typ=OPR_REGISTER) then
  335. begin
  336. if (operands[1].opr.reg.enum in [firstsreg..lastsreg]) or
  337. ((operands[1].opr.reg.enum=R_INTREGISTER) and
  338. (operands[1].opr.reg.number>=nfirstsreg) and
  339. (operands[1].opr.reg.number<=nlastsreg)) then
  340. exit;
  341. end;
  342. if opsize in [S_BW,S_BL,S_WL] then
  343. begin
  344. if ops<>2 then
  345. sizeerr:=true
  346. else
  347. begin
  348. case opsize of
  349. S_BW :
  350. sizeerr:=(operands[1].size<>S_B) or (operands[2].size<>S_W);
  351. S_BL :
  352. sizeerr:=(operands[1].size<>S_B) or (operands[2].size<>S_L);
  353. S_WL :
  354. sizeerr:=(operands[1].size<>S_W) or (operands[2].size<>S_L);
  355. end;
  356. end;
  357. end
  358. else
  359. begin
  360. for i:=1 to ops do
  361. begin
  362. if (operands[i].opr.typ<>OPR_CONSTANT) and
  363. (operands[i].size in [S_B,S_W,S_L]) and
  364. (operands[i].size<>opsize) then
  365. sizeerr:=true;
  366. end;
  367. end;
  368. if sizeerr then
  369. begin
  370. { if range checks are on then generate an error }
  371. if (cs_compilesystem in aktmoduleswitches) or
  372. not (cs_check_range in aktlocalswitches) then
  373. Message(asmr_w_size_suffix_and_dest_dont_match)
  374. else
  375. Message(asmr_e_size_suffix_and_dest_dont_match);
  376. end;
  377. end;
  378. { This check must be done with the operand in ATT order
  379. i.e.after swapping in the intel reader
  380. but before swapping in the NASM and TASM writers PM }
  381. procedure T386Instruction.CheckNonCommutativeOpcodes;
  382. begin
  383. if (OpOrder=op_intel) then
  384. SwapOperands;
  385. if ((ops=2) and
  386. (operands[1].opr.typ=OPR_REGISTER) and
  387. (operands[2].opr.typ=OPR_REGISTER) and
  388. { if the first is ST and the second is also a register
  389. it is necessarily ST1 .. ST7 }
  390. (operands[1].opr.reg.enum in [R_ST..R_ST0])) or
  391. (ops=0) then
  392. if opcode=A_FSUBR then
  393. opcode:=A_FSUB
  394. else if opcode=A_FSUB then
  395. opcode:=A_FSUBR
  396. else if opcode=A_FDIVR then
  397. opcode:=A_FDIV
  398. else if opcode=A_FDIV then
  399. opcode:=A_FDIVR
  400. else if opcode=A_FSUBRP then
  401. opcode:=A_FSUBP
  402. else if opcode=A_FSUBP then
  403. opcode:=A_FSUBRP
  404. else if opcode=A_FDIVRP then
  405. opcode:=A_FDIVP
  406. else if opcode=A_FDIVP then
  407. opcode:=A_FDIVRP;
  408. if ((ops=1) and
  409. (operands[1].opr.typ=OPR_REGISTER) and
  410. (operands[1].opr.reg.enum in [R_ST1..R_ST7])) then
  411. if opcode=A_FSUBRP then
  412. opcode:=A_FSUBP
  413. else if opcode=A_FSUBP then
  414. opcode:=A_FSUBRP
  415. else if opcode=A_FDIVRP then
  416. opcode:=A_FDIVP
  417. else if opcode=A_FDIVP then
  418. opcode:=A_FDIVRP;
  419. end;
  420. {*****************************************************************************
  421. opcode Adding
  422. *****************************************************************************}
  423. procedure T386Instruction.ConcatInstruction(p : taasmoutput);
  424. var
  425. siz : topsize;
  426. i,asize : longint;
  427. ai : taicpu;
  428. begin
  429. if (OpOrder=op_intel) then
  430. SwapOperands;
  431. { Get Opsize }
  432. if (opsize<>S_NO) or (Ops=0) then
  433. siz:=opsize
  434. else
  435. begin
  436. if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
  437. siz:=operands[1].size
  438. else
  439. siz:=operands[Ops].size;
  440. { MOVD should be of size S_LQ or S_QL, but these do not exist PM }
  441. if (ops=2) and (operands[1].size<>S_NO) and
  442. (operands[2].size<>S_NO) and (operands[1].size<>operands[2].size) then
  443. siz:=S_NO;
  444. end;
  445. if ((opcode=A_MOVD)or
  446. (opcode=A_CVTSI2SS)) and
  447. ((operands[1].size=S_NO) or
  448. (operands[2].size=S_NO)) then
  449. siz:=S_NO;
  450. { NASM does not support FADD without args
  451. as alias of FADDP
  452. and GNU AS interprets FADD without operand differently
  453. for version 2.9.1 and 2.9.5 !! }
  454. if (ops=0) and
  455. ((opcode=A_FADD) or
  456. (opcode=A_FMUL) or
  457. (opcode=A_FSUB) or
  458. (opcode=A_FSUBR) or
  459. (opcode=A_FDIV) or
  460. (opcode=A_FDIVR)) then
  461. begin
  462. if opcode=A_FADD then
  463. opcode:=A_FADDP
  464. else if opcode=A_FMUL then
  465. opcode:=A_FMULP
  466. else if opcode=A_FSUB then
  467. opcode:=A_FSUBP
  468. else if opcode=A_FSUBR then
  469. opcode:=A_FSUBRP
  470. else if opcode=A_FDIV then
  471. opcode:=A_FDIVP
  472. else if opcode=A_FDIVR then
  473. opcode:=A_FDIVRP;
  474. {$ifdef ATTOP}
  475. message1(asmr_w_fadd_to_faddp,gas_op2str[opcode]);
  476. {$else}
  477. {$ifdef INTELOP}
  478. message1(asmr_w_fadd_to_faddp,std_op2str[opcode]);
  479. {$else}
  480. message1(asmr_w_fadd_to_faddp,'fXX');
  481. {$endif INTELOP}
  482. {$endif ATTOP}
  483. end;
  484. { GNU AS interprets FDIV without operand differently
  485. for version 2.9.1 and 2.10
  486. we add explicit args to it !! }
  487. if (ops=0) and
  488. ((opcode=A_FSUBP) or
  489. (opcode=A_FSUBRP) or
  490. (opcode=A_FDIVP) or
  491. (opcode=A_FDIVRP) or
  492. (opcode=A_FSUB) or
  493. (opcode=A_FSUBR) or
  494. (opcode=A_FDIV) or
  495. (opcode=A_FDIVR)) then
  496. begin
  497. {$ifdef ATTOP}
  498. message1(asmr_w_adding_explicit_args_fXX,gas_op2str[opcode]);
  499. {$else}
  500. {$ifdef INTELOP}
  501. message1(asmr_w_adding_explicit_args_fXX,std_op2str[opcode]);
  502. {$else}
  503. message1(asmr_w_adding_explicit_args_fXX,'fXX');
  504. {$endif INTELOP}
  505. {$endif ATTOP}
  506. ops:=2;
  507. operands[1].opr.typ:=OPR_REGISTER;
  508. operands[2].opr.typ:=OPR_REGISTER;
  509. operands[1].opr.reg.enum:=R_ST;
  510. operands[2].opr.reg.enum:=R_ST1;
  511. end;
  512. if (ops=1) and
  513. ((operands[1].opr.typ=OPR_REGISTER) and
  514. (operands[1].opr.reg.enum in [R_ST1..R_ST7])) and
  515. ((opcode=A_FSUBP) or
  516. (opcode=A_FSUBRP) or
  517. (opcode=A_FDIVP) or
  518. (opcode=A_FDIVRP) or
  519. (opcode=A_FADDP) or
  520. (opcode=A_FMULP)) then
  521. begin
  522. {$ifdef ATTOP}
  523. message1(asmr_w_adding_explicit_first_arg_fXX,gas_op2str[opcode]);
  524. {$else}
  525. {$ifdef INTELOP}
  526. message1(asmr_w_adding_explicit_first_arg_fXX,std_op2str[opcode]);
  527. {$else}
  528. message1(asmr_w_adding_explicit_first_arg_fXX,'fXX');
  529. {$endif INTELOP}
  530. {$endif ATTOP}
  531. ops:=2;
  532. operands[2].opr.typ:=OPR_REGISTER;
  533. operands[2].opr.reg:=operands[1].opr.reg;
  534. operands[1].opr.reg.enum:=R_ST;
  535. end;
  536. if (ops=1) and
  537. ((operands[1].opr.typ=OPR_REGISTER) and
  538. (operands[1].opr.reg.enum in [R_ST1..R_ST7])) and
  539. ((opcode=A_FSUB) or
  540. (opcode=A_FSUBR) or
  541. (opcode=A_FDIV) or
  542. (opcode=A_FDIVR) or
  543. (opcode=A_FADD) or
  544. (opcode=A_FMUL)) then
  545. begin
  546. {$ifdef ATTOP}
  547. message1(asmr_w_adding_explicit_second_arg_fXX,gas_op2str[opcode]);
  548. {$else}
  549. {$ifdef INTELOP}
  550. message1(asmr_w_adding_explicit_second_arg_fXX,std_op2str[opcode]);
  551. {$else}
  552. message1(asmr_w_adding_explicit_second_arg_fXX,'fXX');
  553. {$endif INTELOP}
  554. {$endif ATTOP}
  555. ops:=2;
  556. operands[2].opr.typ:=OPR_REGISTER;
  557. operands[2].opr.reg.enum:=R_ST;
  558. end;
  559. { I tried to convince Linus Torvalds to add
  560. code to support ENTER instruction
  561. (when raising a stack page fault)
  562. but he replied that ENTER is a bad instruction and
  563. Linux does not need to support it
  564. So I think its at least a good idea to add a warning
  565. if someone uses this in assembler code
  566. FPC itself does not use it at all PM }
  567. if (opcode=A_ENTER) and ((target_info.system=system_i386_linux) or
  568. (target_info.system=system_i386_FreeBSD)) then
  569. message(asmr_w_enter_not_supported_by_linux);
  570. ai:=taicpu.op_none(opcode,siz);
  571. ai.SetOperandOrder(OpOrder);
  572. ai.Ops:=Ops;
  573. for i:=1to Ops do
  574. begin
  575. case operands[i].opr.typ of
  576. OPR_CONSTANT :
  577. ai.loadconst(i-1,aword(operands[i].opr.val));
  578. OPR_REGISTER:
  579. ai.loadreg(i-1,operands[i].opr.reg);
  580. OPR_SYMBOL:
  581. ai.loadsymbol(i-1,operands[i].opr.symbol,operands[i].opr.symofs);
  582. OPR_REFERENCE:
  583. begin
  584. ai.loadref(i-1,operands[i].opr.ref);
  585. if operands[i].size<>S_NO then
  586. begin
  587. asize:=0;
  588. case operands[i].size of
  589. S_B :
  590. asize:=OT_BITS8;
  591. S_W, S_IS :
  592. asize:=OT_BITS16;
  593. S_L, S_IL, S_FS:
  594. asize:=OT_BITS32;
  595. S_Q, S_D, S_FL, S_FV :
  596. asize:=OT_BITS64;
  597. S_FX :
  598. asize:=OT_BITS80;
  599. end;
  600. if asize<>0 then
  601. ai.oper[i-1].ot:=(ai.oper[i-1].ot and not OT_SIZE_MASK) or asize;
  602. end;
  603. end;
  604. end;
  605. end;
  606. if (opcode=A_CALL) and (opsize=S_FAR) then
  607. opcode:=A_LCALL;
  608. if (opcode=A_JMP) and (opsize=S_FAR) then
  609. opcode:=A_LJMP;
  610. if (opcode=A_LCALL) or (opcode=A_LJMP) then
  611. opsize:=S_FAR;
  612. { Condition ? }
  613. if condition<>C_None then
  614. ai.SetCondition(condition);
  615. { Concat the opcode or give an error }
  616. if assigned(ai) then
  617. begin
  618. { Check the instruction if it's valid }
  619. {$ifndef NOAG386BIN}
  620. ai.CheckIfValid;
  621. {$endif NOAG386BIN}
  622. p.concat(ai);
  623. end
  624. else
  625. Message(asmr_e_invalid_opcode_and_operand);
  626. end;
  627. end.
  628. {
  629. $Log$
  630. Revision 1.1 2003-04-30 15:45:35 florian
  631. * merged more x86-64/i386 code
  632. Revision 1.30 2003/04/25 12:04:31 florian
  633. * merged agx64att and ag386att to x86/agx86att
  634. Revision 1.29 2003/02/19 22:00:16 daniel
  635. * Code generator converted to new register notation
  636. - Horribily outdated todo.txt removed
  637. Revision 1.28 2003/02/03 22:47:14 daniel
  638. - Removed reg_2_opsize array
  639. Revision 1.27 2003/01/08 18:43:57 daniel
  640. * Tregister changed into a record
  641. Revision 1.26 2002/11/15 01:58:58 peter
  642. * merged changes from 1.0.7 up to 04-11
  643. - -V option for generating bug report tracing
  644. - more tracing for option parsing
  645. - errors for cdecl and high()
  646. - win32 import stabs
  647. - win32 records<=8 are returned in eax:edx (turned off by default)
  648. - heaptrc update
  649. - more info for temp management in .s file with EXTDEBUG
  650. Revision 1.25 2002/10/31 13:28:32 pierre
  651. * correct last wrong fix for tw2158
  652. Revision 1.24 2002/10/30 17:10:00 pierre
  653. * merge of fix for tw2158 bug
  654. Revision 1.23 2002/07/26 21:15:44 florian
  655. * rewrote the system handling
  656. Revision 1.22 2002/07/01 18:46:34 peter
  657. * internal linker
  658. * reorganized aasm layer
  659. Revision 1.21 2002/05/18 13:34:25 peter
  660. * readded missing revisions
  661. Revision 1.20 2002/05/16 19:46:52 carl
  662. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  663. + try to fix temp allocation (still in ifdef)
  664. + generic constructor calls
  665. + start of tassembler / tmodulebase class cleanup
  666. Revision 1.18 2002/05/12 16:53:18 peter
  667. * moved entry and exitcode to ncgutil and cgobj
  668. * foreach gets extra argument for passing local data to the
  669. iterator function
  670. * -CR checks also class typecasts at runtime by changing them
  671. into as
  672. * fixed compiler to cycle with the -CR option
  673. * fixed stabs with elf writer, finally the global variables can
  674. be watched
  675. * removed a lot of routines from cga unit and replaced them by
  676. calls to cgobj
  677. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  678. u32bit then the other is typecasted also to u32bit without giving
  679. a rangecheck warning/error.
  680. * fixed pascal calling method with reversing also the high tree in
  681. the parast, detected by tcalcst3 test
  682. Revision 1.17 2002/04/15 19:12:09 carl
  683. + target_info.size_of_pointer -> pointer_size
  684. + some cleanup of unused types/variables
  685. * move several constants from cpubase to their specific units
  686. (where they are used)
  687. + att_Reg2str -> gas_reg2str
  688. + int_reg2str -> std_reg2str
  689. Revision 1.16 2002/04/04 19:06:13 peter
  690. * removed unused units
  691. * use tlocation.size in cg.a_*loc*() routines
  692. Revision 1.15 2002/04/02 17:11:39 peter
  693. * tlocation,treference update
  694. * LOC_CONSTANT added for better constant handling
  695. * secondadd splitted in multiple routines
  696. * location_force_reg added for loading a location to a register
  697. of a specified size
  698. * secondassignment parses now first the right and then the left node
  699. (this is compatible with Kylix). This saves a lot of push/pop especially
  700. with string operations
  701. * adapted some routines to use the new cg methods
  702. Revision 1.14 2002/01/24 18:25:53 peter
  703. * implicit result variable generation for assembler routines
  704. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  705. }