ra386.pas 22 KB

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