cpuasm.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
  4. Contains the assembler object for the i386
  5. * This code was inspired by the NASM sources
  6. The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. unit cpuasm;
  22. {$i defines.inc}
  23. { Optimize addressing and skip already passed nodes }
  24. {$ifndef NASMDEBUG}
  25. {$define OPTEA}
  26. {$define PASS2FLAG}
  27. {$endif ndef NASMDEBUG}
  28. { Give warnings when an immediate is found in the reference struct }
  29. {.$define REF_IMMEDIATE_WARN}
  30. interface
  31. uses
  32. cobjects,
  33. aasm,globals,verbose,
  34. cpubase;
  35. const
  36. MaxPrefixes=4;
  37. type
  38. pairegalloc = ^tairegalloc;
  39. tairegalloc = object(tai)
  40. allocation : boolean;
  41. reg : tregister;
  42. constructor alloc(r : tregister);
  43. constructor dealloc(r : tregister);
  44. end;
  45. { alignment for operator }
  46. pai_align = ^tai_align;
  47. tai_align = object(tai_align_abstract)
  48. reg : tregister;
  49. constructor init(b:byte);
  50. constructor init_op(b: byte; _op: byte);
  51. function getfillbuf:pchar;
  52. end;
  53. paicpu = ^taicpu;
  54. taicpu = object(tai)
  55. is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
  56. opcode : tasmop;
  57. opsize : topsize;
  58. condition : TAsmCond;
  59. ops : longint;
  60. oper : array[0..2] of toper;
  61. constructor op_none(op : tasmop;_size : topsize);
  62. constructor op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  63. constructor op_const(op : tasmop;_size : topsize;_op1 : longint);
  64. constructor op_ref(op : tasmop;_size : topsize;_op1 : preference);
  65. constructor op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  66. constructor op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
  67. constructor op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
  68. constructor op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
  69. constructor op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
  70. constructor op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
  71. constructor op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
  72. { this is only allowed if _op1 is an int value (_op1^.isintvalue=true) }
  73. constructor op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
  74. constructor op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  75. constructor op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
  76. constructor op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
  77. constructor op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister; _op3 : preference);
  78. constructor op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
  79. { this is for Jmp instructions }
  80. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : pasmsymbol);
  81. constructor op_sym(op : tasmop;_size : topsize;_op1 : pasmsymbol);
  82. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint);
  83. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : tregister);
  84. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : preference);
  85. procedure loadconst(opidx:longint;l:longint);
  86. procedure loadsymbol(opidx:longint;s:pasmsymbol;sofs:longint);
  87. procedure loadref(opidx:longint;p:preference);
  88. procedure loadreg(opidx:longint;r:tregister);
  89. procedure loadoper(opidx:longint;o:toper);
  90. procedure changeopsize(siz:topsize);
  91. procedure SetCondition(c:TAsmCond);
  92. destructor done;virtual;
  93. function getcopy:plinkedlist_item;virtual;
  94. function GetString:string;
  95. procedure SwapOperands;
  96. procedure CheckNonCommutativeOpcodes;
  97. private
  98. segprefix : tregister;
  99. procedure init(op : tasmop;_size : topsize); { this need to be called by all constructor }
  100. {$ifndef NOAG386BIN}
  101. public
  102. { the next will reset all instructions that can change in pass 2 }
  103. procedure ResetPass2;
  104. function Pass1(offset:longint):longint;virtual;
  105. procedure Pass2;virtual;
  106. private
  107. { next fields are filled in pass1, so pass2 is faster }
  108. insentry : PInsEntry;
  109. insoffset,
  110. inssize : longint;
  111. LastInsOffset : longint; { need to be public to be reset }
  112. function InsEnd:longint;
  113. procedure create_ot;
  114. function Matches(p:PInsEntry):longint;
  115. function calcsize(p:PInsEntry):longint;
  116. procedure gencode;
  117. function NeedAddrPrefix(opidx:byte):boolean;
  118. {$endif NOAG386BIN}
  119. end;
  120. implementation
  121. uses
  122. cutils,og386;
  123. {*****************************************************************************
  124. TaiRegAlloc
  125. *****************************************************************************}
  126. constructor tairegalloc.alloc(r : tregister);
  127. begin
  128. inherited init;
  129. typ:=ait_regalloc;
  130. allocation:=true;
  131. reg:=r;
  132. end;
  133. constructor tairegalloc.dealloc(r : tregister);
  134. begin
  135. inherited init;
  136. typ:=ait_regalloc;
  137. allocation:=false;
  138. reg:=r;
  139. end;
  140. {****************************************************************************
  141. TAI_ALIGN
  142. ****************************************************************************}
  143. constructor tai_align.init(b: byte);
  144. begin
  145. inherited init(b);
  146. reg := R_ECX;
  147. end;
  148. constructor tai_align.init_op(b: byte; _op: byte);
  149. begin
  150. inherited init_op(b,_op);
  151. reg := R_NO;
  152. end;
  153. function tai_align.getfillbuf:pchar;
  154. const
  155. alignarray:array[0..5] of string[8]=(
  156. #$8D#$B4#$26#$00#$00#$00#$00,
  157. #$8D#$B6#$00#$00#$00#$00,
  158. #$8D#$74#$26#$00,
  159. #$8D#$76#$00,
  160. #$89#$F6,
  161. #$90
  162. );
  163. var
  164. bufptr : pchar;
  165. j : longint;
  166. begin
  167. if not use_op then
  168. begin
  169. bufptr:=@buf;
  170. while (fillsize>0) do
  171. begin
  172. for j:=0 to 5 do
  173. if (fillsize>=length(alignarray[j])) then
  174. break;
  175. move(alignarray[j][1],bufptr^,length(alignarray[j]));
  176. inc(bufptr,length(alignarray[j]));
  177. dec(fillsize,length(alignarray[j]));
  178. end;
  179. end;
  180. getfillbuf:=pchar(@buf);
  181. end;
  182. {*****************************************************************************
  183. Taicpu Constructors
  184. *****************************************************************************}
  185. procedure taicpu.loadconst(opidx:longint;l:longint);
  186. begin
  187. if opidx>=ops then
  188. ops:=opidx+1;
  189. with oper[opidx] do
  190. begin
  191. if typ=top_ref then
  192. disposereference(ref);
  193. val:=l;
  194. typ:=top_const;
  195. end;
  196. end;
  197. procedure taicpu.loadsymbol(opidx:longint;s:pasmsymbol;sofs:longint);
  198. begin
  199. if opidx>=ops then
  200. ops:=opidx+1;
  201. with oper[opidx] do
  202. begin
  203. if typ=top_ref then
  204. disposereference(ref);
  205. sym:=s;
  206. symofs:=sofs;
  207. typ:=top_symbol;
  208. end;
  209. { Mark the symbol as used }
  210. if assigned(s) then
  211. inc(s^.refs);
  212. end;
  213. procedure taicpu.loadref(opidx:longint;p:preference);
  214. begin
  215. if opidx>=ops then
  216. ops:=opidx+1;
  217. with oper[opidx] do
  218. begin
  219. if typ=top_ref then
  220. disposereference(ref);
  221. if p^.is_immediate then
  222. begin
  223. {$ifdef REF_IMMEDIATE_WARN}
  224. Comment(V_Warning,'Reference immediate');
  225. {$endif}
  226. val:=p^.offset;
  227. disposereference(p);
  228. typ:=top_const;
  229. end
  230. else
  231. begin
  232. ref:=p;
  233. if not(ref^.segment in [R_DS,R_NO]) then
  234. segprefix:=ref^.segment;
  235. typ:=top_ref;
  236. { mark symbol as used }
  237. if assigned(ref^.symbol) then
  238. inc(ref^.symbol^.refs);
  239. end;
  240. end;
  241. end;
  242. procedure taicpu.loadreg(opidx:longint;r:tregister);
  243. begin
  244. if opidx>=ops then
  245. ops:=opidx+1;
  246. with oper[opidx] do
  247. begin
  248. if typ=top_ref then
  249. disposereference(ref);
  250. reg:=r;
  251. typ:=top_reg;
  252. end;
  253. end;
  254. procedure taicpu.loadoper(opidx:longint;o:toper);
  255. begin
  256. if opidx>=ops then
  257. ops:=opidx+1;
  258. if oper[opidx].typ=top_ref then
  259. disposereference(oper[opidx].ref);
  260. oper[opidx]:=o;
  261. { copy also the reference }
  262. if oper[opidx].typ=top_ref then
  263. oper[opidx].ref:=newreference(o.ref^);
  264. end;
  265. procedure taicpu.changeopsize(siz:topsize);
  266. begin
  267. opsize:=siz;
  268. end;
  269. procedure taicpu.init(op : tasmop;_size : topsize);
  270. begin
  271. typ:=ait_instruction;
  272. is_jmp:=false;
  273. segprefix:=R_NO;
  274. opcode:=op;
  275. opsize:=_size;
  276. ops:=0;
  277. condition:=c_none;
  278. fillchar(oper,sizeof(oper),0);
  279. {$ifndef NOAG386BIN}
  280. insentry:=nil;
  281. LastInsOffset:=-1;
  282. InsOffset:=0;
  283. InsSize:=0;
  284. {$endif}
  285. end;
  286. constructor taicpu.op_none(op : tasmop;_size : topsize);
  287. begin
  288. inherited init;
  289. init(op,_size);
  290. end;
  291. constructor taicpu.op_reg(op : tasmop;_size : topsize;_op1 : tregister);
  292. begin
  293. inherited init;
  294. init(op,_size);
  295. ops:=1;
  296. loadreg(0,_op1);
  297. end;
  298. constructor taicpu.op_const(op : tasmop;_size : topsize;_op1 : longint);
  299. begin
  300. inherited init;
  301. init(op,_size);
  302. ops:=1;
  303. loadconst(0,_op1);
  304. end;
  305. constructor taicpu.op_ref(op : tasmop;_size : topsize;_op1 : preference);
  306. begin
  307. inherited init;
  308. init(op,_size);
  309. ops:=1;
  310. loadref(0,_op1);
  311. end;
  312. constructor taicpu.op_reg_reg(op : tasmop;_size : topsize;_op1,_op2 : tregister);
  313. begin
  314. inherited init;
  315. init(op,_size);
  316. ops:=2;
  317. loadreg(0,_op1);
  318. loadreg(1,_op2);
  319. end;
  320. constructor taicpu.op_reg_const(op:tasmop; _size: topsize; _op1: tregister; _op2: longint);
  321. begin
  322. inherited init;
  323. init(op,_size);
  324. ops:=2;
  325. loadreg(0,_op1);
  326. loadconst(1,_op2);
  327. end;
  328. constructor taicpu.op_reg_ref(op : tasmop;_size : topsize;_op1 : tregister;_op2 : preference);
  329. begin
  330. inherited init;
  331. init(op,_size);
  332. ops:=2;
  333. loadreg(0,_op1);
  334. loadref(1,_op2);
  335. end;
  336. constructor taicpu.op_const_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister);
  337. begin
  338. inherited init;
  339. init(op,_size);
  340. ops:=2;
  341. loadconst(0,_op1);
  342. loadreg(1,_op2);
  343. end;
  344. constructor taicpu.op_const_const(op : tasmop;_size : topsize;_op1,_op2 : longint);
  345. begin
  346. inherited init;
  347. init(op,_size);
  348. ops:=2;
  349. loadconst(0,_op1);
  350. loadconst(1,_op2);
  351. end;
  352. constructor taicpu.op_const_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference);
  353. begin
  354. inherited init;
  355. init(op,_size);
  356. ops:=2;
  357. loadconst(0,_op1);
  358. loadref(1,_op2);
  359. end;
  360. constructor taicpu.op_ref_reg(op : tasmop;_size : topsize;_op1 : preference;_op2 : tregister);
  361. begin
  362. inherited init;
  363. init(op,_size);
  364. ops:=2;
  365. loadref(0,_op1);
  366. loadreg(1,_op2);
  367. end;
  368. constructor taicpu.op_ref_ref(op : tasmop;_size : topsize;_op1,_op2 : preference);
  369. begin
  370. inherited init;
  371. init(op,_size);
  372. ops:=2;
  373. loadref(0,_op1);
  374. loadref(1,_op2);
  375. end;
  376. constructor taicpu.op_reg_reg_reg(op : tasmop;_size : topsize;_op1,_op2,_op3 : tregister);
  377. begin
  378. inherited init;
  379. init(op,_size);
  380. ops:=3;
  381. loadreg(0,_op1);
  382. loadreg(1,_op2);
  383. loadreg(2,_op3);
  384. end;
  385. constructor taicpu.op_const_reg_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : tregister);
  386. begin
  387. inherited init;
  388. init(op,_size);
  389. ops:=3;
  390. loadconst(0,_op1);
  391. loadreg(1,_op2);
  392. loadreg(2,_op3);
  393. end;
  394. constructor taicpu.op_reg_reg_ref(op : tasmop;_size : topsize;_op1,_op2 : tregister;_op3 : preference);
  395. begin
  396. inherited init;
  397. init(op,_size);
  398. ops:=3;
  399. loadreg(0,_op1);
  400. loadreg(1,_op2);
  401. loadref(2,_op3);
  402. end;
  403. constructor taicpu.op_const_ref_reg(op : tasmop;_size : topsize;_op1 : longint;_op2 : preference;_op3 : tregister);
  404. begin
  405. inherited init;
  406. init(op,_size);
  407. ops:=3;
  408. loadconst(0,_op1);
  409. loadref(1,_op2);
  410. loadreg(2,_op3);
  411. end;
  412. constructor taicpu.op_const_reg_ref(op : tasmop;_size : topsize;_op1 : longint;_op2 : tregister;_op3 : preference);
  413. begin
  414. inherited init;
  415. init(op,_size);
  416. ops:=3;
  417. loadconst(0,_op1);
  418. loadreg(1,_op2);
  419. loadref(2,_op3);
  420. end;
  421. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_size : topsize;_op1 : pasmsymbol);
  422. begin
  423. inherited init;
  424. init(op,_size);
  425. condition:=cond;
  426. ops:=1;
  427. loadsymbol(0,_op1,0);
  428. end;
  429. constructor taicpu.op_sym(op : tasmop;_size : topsize;_op1 : pasmsymbol);
  430. begin
  431. inherited init;
  432. init(op,_size);
  433. ops:=1;
  434. loadsymbol(0,_op1,0);
  435. end;
  436. constructor taicpu.op_sym_ofs(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint);
  437. begin
  438. inherited init;
  439. init(op,_size);
  440. ops:=1;
  441. loadsymbol(0,_op1,_op1ofs);
  442. end;
  443. constructor taicpu.op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : tregister);
  444. begin
  445. inherited init;
  446. init(op,_size);
  447. ops:=2;
  448. loadsymbol(0,_op1,_op1ofs);
  449. loadreg(1,_op2);
  450. end;
  451. constructor taicpu.op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : pasmsymbol;_op1ofs:longint;_op2 : preference);
  452. begin
  453. inherited init;
  454. init(op,_size);
  455. ops:=2;
  456. loadsymbol(0,_op1,_op1ofs);
  457. loadref(1,_op2);
  458. end;
  459. destructor taicpu.done;
  460. var
  461. i : longint;
  462. begin
  463. if is_jmp then
  464. dec(PasmLabel(oper[0].sym)^.refs)
  465. else
  466. for i:=1 to ops do
  467. if (oper[i-1].typ=top_ref) then
  468. dispose(oper[i-1].ref);
  469. inherited done;
  470. end;
  471. function taicpu.getcopy:plinkedlist_item;
  472. var
  473. i : longint;
  474. p : plinkedlist_item;
  475. begin
  476. p:=inherited getcopy;
  477. { make a copy of the references }
  478. for i:=1 to ops do
  479. if (paicpu(p)^.oper[i-1].typ=top_ref) then
  480. begin
  481. new(paicpu(p)^.oper[i-1].ref);
  482. paicpu(p)^.oper[i-1].ref^:=oper[i-1].ref^;
  483. end;
  484. getcopy:=p;
  485. end;
  486. procedure taicpu.SetCondition(c:TAsmCond);
  487. begin
  488. condition:=c;
  489. end;
  490. function taicpu.GetString:string;
  491. var
  492. i : longint;
  493. s : string;
  494. addsize : boolean;
  495. begin
  496. s:='['+int_op2str[opcode];
  497. for i:=1to ops do
  498. begin
  499. if i=1 then
  500. s:=s+' '
  501. else
  502. s:=s+',';
  503. { type }
  504. addsize:=false;
  505. if (oper[i-1].ot and OT_XMMREG)=OT_XMMREG then
  506. s:=s+'xmmreg'
  507. else
  508. if (oper[i-1].ot and OT_MMXREG)=OT_MMXREG then
  509. s:=s+'mmxreg'
  510. else
  511. if (oper[i-1].ot and OT_FPUREG)=OT_FPUREG then
  512. s:=s+'fpureg'
  513. else
  514. if (oper[i-1].ot and OT_REGISTER)=OT_REGISTER then
  515. begin
  516. s:=s+'reg';
  517. addsize:=true;
  518. end
  519. else
  520. if (oper[i-1].ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  521. begin
  522. s:=s+'imm';
  523. addsize:=true;
  524. end
  525. else
  526. if (oper[i-1].ot and OT_MEMORY)=OT_MEMORY then
  527. begin
  528. s:=s+'mem';
  529. addsize:=true;
  530. end
  531. else
  532. s:=s+'???';
  533. { size }
  534. if addsize then
  535. begin
  536. if (oper[i-1].ot and OT_BITS8)<>0 then
  537. s:=s+'8'
  538. else
  539. if (oper[i-1].ot and OT_BITS16)<>0 then
  540. s:=s+'16'
  541. else
  542. if (oper[i-1].ot and OT_BITS32)<>0 then
  543. s:=s+'32'
  544. else
  545. s:=s+'??';
  546. { signed }
  547. if (oper[i-1].ot and OT_SIGNED)<>0 then
  548. s:=s+'s';
  549. end;
  550. end;
  551. GetString:=s+']';
  552. end;
  553. procedure taicpu.SwapOperands;
  554. var
  555. p : TOper;
  556. begin
  557. { Fix the operands which are in AT&T style and we need them in Intel style }
  558. case ops of
  559. 2 : begin
  560. { 0,1 -> 1,0 }
  561. p:=oper[0];
  562. oper[0]:=oper[1];
  563. oper[1]:=p;
  564. end;
  565. 3 : begin
  566. { 0,1,2 -> 2,1,0 }
  567. p:=oper[0];
  568. oper[0]:=oper[2];
  569. oper[2]:=p;
  570. end;
  571. end;
  572. end;
  573. { This check must be done with the operand in ATT order
  574. i.e.after swapping in the intel reader
  575. but before swapping in the NASM and TASM writers PM }
  576. procedure taicpu.CheckNonCommutativeOpcodes;
  577. begin
  578. if ((ops=2) and
  579. (oper[0].typ=top_reg) and
  580. (oper[1].typ=top_reg) and
  581. { if the first is ST and the second is also a register
  582. it is necessarily ST1 .. ST7 }
  583. (oper[0].reg=R_ST)) or
  584. ((ops=1) and
  585. (oper[0].typ=top_reg) and
  586. (oper[0].reg in [R_ST1..R_ST7])) or
  587. (ops=0) then
  588. if opcode=A_FSUBR then
  589. opcode:=A_FSUB
  590. else if opcode=A_FSUB then
  591. opcode:=A_FSUBR
  592. else if opcode=A_FDIVR then
  593. opcode:=A_FDIV
  594. else if opcode=A_FDIV then
  595. opcode:=A_FDIVR
  596. else if opcode=A_FSUBRP then
  597. opcode:=A_FSUBP
  598. else if opcode=A_FSUBP then
  599. opcode:=A_FSUBRP
  600. else if opcode=A_FDIVRP then
  601. opcode:=A_FDIVP
  602. else if opcode=A_FDIVP then
  603. opcode:=A_FDIVRP;
  604. end;
  605. {*****************************************************************************
  606. Assembler
  607. *****************************************************************************}
  608. {$ifndef NOAG386BIN}
  609. type
  610. ea=packed record
  611. sib_present : boolean;
  612. bytes : byte;
  613. size : byte;
  614. modrm : byte;
  615. sib : byte;
  616. end;
  617. procedure taicpu.create_ot;
  618. {
  619. this function will also fix some other fields which only needs to be once
  620. }
  621. var
  622. i,l,relsize : longint;
  623. begin
  624. if ops=0 then
  625. exit;
  626. { update oper[].ot field }
  627. for i:=0 to ops-1 do
  628. with oper[i] do
  629. begin
  630. case typ of
  631. top_reg :
  632. ot:=reg_2_type[reg];
  633. top_ref :
  634. begin
  635. { create ot field }
  636. ot:=OT_MEMORY or opsize_2_type[i,opsize];
  637. if (ref^.base=R_NO) and (ref^.index=R_NO) then
  638. ot:=ot or OT_MEM_OFFS;
  639. { handle also the offsetfixup }
  640. inc(ref^.offset,ref^.offsetfixup);
  641. ref^.offsetfixup:=0;
  642. { fix scalefactor }
  643. if (ref^.index=R_NO) then
  644. ref^.scalefactor:=0
  645. else
  646. if (ref^.scalefactor=0) then
  647. ref^.scalefactor:=1;
  648. end;
  649. top_const :
  650. begin
  651. if (opsize<>S_W) and (val>=-128) and (val<=127) then
  652. ot:=OT_IMM8 or OT_SIGNED
  653. else
  654. ot:=OT_IMMEDIATE or opsize_2_type[i,opsize];
  655. end;
  656. top_symbol :
  657. begin
  658. if LastInsOffset=-1 then
  659. l:=0
  660. else
  661. l:=InsOffset-LastInsOffset;
  662. inc(l,symofs);
  663. if assigned(sym) then
  664. inc(l,sym^.address);
  665. { instruction size will then always become 2 (PFV) }
  666. relsize:=(InsOffset+2)-l;
  667. if (not assigned(sym) or
  668. ((sym^.bind<>AB_EXTERNAL) and (sym^.address<>0))) and
  669. (relsize>=-128) and (relsize<=127) then
  670. ot:=OT_IMM32 or OT_SHORT
  671. else
  672. ot:=OT_IMM32 or OT_NEAR;
  673. end;
  674. end;
  675. end;
  676. end;
  677. function taicpu.InsEnd:longint;
  678. begin
  679. InsEnd:=InsOffset+InsSize;
  680. end;
  681. function taicpu.Matches(p:PInsEntry):longint;
  682. { * IF_SM stands for Size Match: any operand whose size is not
  683. * explicitly specified by the template is `really' intended to be
  684. * the same size as the first size-specified operand.
  685. * Non-specification is tolerated in the input instruction, but
  686. * _wrong_ specification is not.
  687. *
  688. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  689. * three-operand instructions such as SHLD: it implies that the
  690. * first two operands must match in size, but that the third is
  691. * required to be _unspecified_.
  692. *
  693. * IF_SB invokes Size Byte: operands with unspecified size in the
  694. * template are really bytes, and so no non-byte specification in
  695. * the input instruction will be tolerated. IF_SW similarly invokes
  696. * Size Word, and IF_SD invokes Size Doubleword.
  697. *
  698. * (The default state if neither IF_SM nor IF_SM2 is specified is
  699. * that any operand with unspecified size in the template is
  700. * required to have unspecified size in the instruction too...)
  701. }
  702. var
  703. i,j,asize,oprs : longint;
  704. siz : array[0..2] of longint;
  705. begin
  706. Matches:=100;
  707. { Check the opcode and operands }
  708. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  709. begin
  710. Matches:=0;
  711. exit;
  712. end;
  713. { Check that no spurious colons or TOs are present }
  714. for i:=0 to p^.ops-1 do
  715. if (oper[i].ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  716. begin
  717. Matches:=0;
  718. exit;
  719. end;
  720. { Check that the operand flags all match up }
  721. for i:=0 to p^.ops-1 do
  722. begin
  723. if (p^.optypes[i] and (not oper[i].ot) or
  724. ((p^.optypes[i] and OT_SIZE_MASK) and
  725. ((p^.optypes[i] xor oper[i].ot) and OT_SIZE_MASK)))<>0 then
  726. begin
  727. if ((p^.optypes[i] and (not oper[i].ot) and OT_NON_SIZE) or
  728. (oper[i].ot and OT_SIZE_MASK))<>0 then
  729. begin
  730. Matches:=0;
  731. exit;
  732. end
  733. else
  734. Matches:=1;
  735. end;
  736. end;
  737. { Check operand sizes }
  738. { as default an untyped size can get all the sizes, this is different
  739. from nasm, but else we need to do a lot checking which opcodes want
  740. size or not with the automatic size generation }
  741. asize:=$ffffffff;
  742. if (p^.flags and IF_SB)<>0 then
  743. asize:=OT_BITS8
  744. else if (p^.flags and IF_SW)<>0 then
  745. asize:=OT_BITS16
  746. else if (p^.flags and IF_SD)<>0 then
  747. asize:=OT_BITS32;
  748. if (p^.flags and IF_ARMASK)<>0 then
  749. begin
  750. siz[0]:=0;
  751. siz[1]:=0;
  752. siz[2]:=0;
  753. if (p^.flags and IF_AR0)<>0 then
  754. siz[0]:=asize
  755. else if (p^.flags and IF_AR1)<>0 then
  756. siz[1]:=asize
  757. else if (p^.flags and IF_AR2)<>0 then
  758. siz[2]:=asize;
  759. end
  760. else
  761. begin
  762. { siz[0]:=asize;
  763. siz[1]:=asize;
  764. siz[2]:=asize; }
  765. { we can leave because the size for all operands is forced to be
  766. the same }
  767. exit;
  768. end;
  769. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  770. begin
  771. if (p^.flags and IF_SM2)<>0 then
  772. oprs:=2
  773. else
  774. oprs:=p^.ops;
  775. for i:=0 to oprs-1 do
  776. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  777. begin
  778. for j:=0 to oprs-1 do
  779. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  780. break;
  781. end;
  782. end
  783. else
  784. oprs:=2;
  785. { Check operand sizes }
  786. for i:=0to p^.ops-1 do
  787. begin
  788. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  789. ((oper[i].ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  790. { Immediates can always include smaller size }
  791. ((oper[i].ot and OT_IMMEDIATE)=0) and
  792. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i].ot and OT_SIZE_MASK)) then
  793. Matches:=2;
  794. end;
  795. end;
  796. procedure taicpu.ResetPass2;
  797. begin
  798. { we are here in a second pass, check if the instruction can be optimized }
  799. if assigned(InsEntry) and
  800. ((InsEntry^.flags and IF_PASS2)<>0) then
  801. begin
  802. InsEntry:=nil;
  803. InsSize:=0;
  804. end;
  805. LastInsOffset:=-1;
  806. end;
  807. function taicpu.Pass1(offset:longint):longint;
  808. var
  809. m,i : longint;
  810. begin
  811. Pass1:=0;
  812. { Save the old offset and set the new offset }
  813. InsOffset:=Offset;
  814. { Things which may only be done once, not when a second pass is done to
  815. optimize }
  816. if Insentry=nil then
  817. begin
  818. { Check if error last time then InsSize=-1 }
  819. if InsSize=-1 then
  820. exit;
  821. { We need intel style operands }
  822. SwapOperands;
  823. { create the .ot fields }
  824. create_ot;
  825. { set the file postion }
  826. aktfilepos:=fileinfo;
  827. end
  828. else
  829. begin
  830. {$ifdef PASS2FLAG}
  831. { we are here in a second pass, check if the instruction can be optimized }
  832. if (InsEntry^.flags and IF_PASS2)=0 then
  833. begin
  834. Pass1:=InsSize;
  835. exit;
  836. end;
  837. { update the .ot fields, some top_const can be updated }
  838. create_ot;
  839. {$endif}
  840. end;
  841. { Lookup opcode in the table }
  842. InsSize:=-1;
  843. i:=instabcache^[opcode];
  844. if i=-1 then
  845. begin
  846. Message1(asmw_e_opcode_not_in_table,att_op2str[opcode]);
  847. exit;
  848. end;
  849. insentry:=@instab[i];
  850. while (insentry^.opcode=opcode) do
  851. begin
  852. m:=matches(insentry);
  853. if m=100 then
  854. begin
  855. InsSize:=calcsize(insentry);
  856. if (segprefix<>R_NO) then
  857. inc(InsSize);
  858. Pass1:=InsSize;
  859. LastInsOffset:=InsOffset;
  860. exit;
  861. end;
  862. inc(i);
  863. insentry:=@instab[i];
  864. end;
  865. if insentry^.opcode<>opcode then
  866. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  867. { No instruction found, set insentry to nil and inssize to -1 }
  868. insentry:=nil;
  869. inssize:=-1;
  870. LastInsOffset:=-1;
  871. end;
  872. procedure taicpu.Pass2;
  873. var
  874. c : longint;
  875. begin
  876. { error in pass1 ? }
  877. if insentry=nil then
  878. exit;
  879. aktfilepos:=fileinfo;
  880. { Segment override }
  881. if (segprefix<>R_NO) then
  882. begin
  883. case segprefix of
  884. R_CS : c:=$2e;
  885. R_DS : c:=$3e;
  886. R_ES : c:=$26;
  887. R_FS : c:=$64;
  888. R_GS : c:=$65;
  889. R_SS : c:=$36;
  890. end;
  891. objectoutput^.writebytes(c,1);
  892. { fix the offset for GenNode }
  893. inc(InsOffset);
  894. end;
  895. { Generate the instruction }
  896. GenCode;
  897. end;
  898. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  899. var
  900. i,b : tregister;
  901. begin
  902. if (OT_MEMORY and (not oper[opidx].ot))=0 then
  903. begin
  904. i:=oper[opidx].ref^.index;
  905. b:=oper[opidx].ref^.base;
  906. if not(i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) or
  907. not(b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) then
  908. begin
  909. NeedAddrPrefix:=true;
  910. exit;
  911. end;
  912. end;
  913. NeedAddrPrefix:=false;
  914. end;
  915. function regval(r:tregister):byte;
  916. begin
  917. case r of
  918. R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0 :
  919. regval:=0;
  920. R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1 :
  921. regval:=1;
  922. R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2 :
  923. regval:=2;
  924. R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3 :
  925. regval:=3;
  926. R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4 :
  927. regval:=4;
  928. R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5 :
  929. regval:=5;
  930. R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6 :
  931. regval:=6;
  932. R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7 :
  933. regval:=7;
  934. else
  935. begin
  936. internalerror(777001);
  937. regval:=0;
  938. end;
  939. end;
  940. end;
  941. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  942. const
  943. regs : array[0..63] of tregister=(
  944. R_MM0, R_EAX, R_AX, R_AL, R_XMM0, R_NO, R_NO, R_NO,
  945. R_MM1, R_ECX, R_CX, R_CL, R_XMM1, R_NO, R_NO, R_NO,
  946. R_MM2, R_EDX, R_DX, R_DL, R_XMM2, R_NO, R_NO, R_NO,
  947. R_MM3, R_EBX, R_BX, R_BL, R_XMM3, R_NO, R_NO, R_NO,
  948. R_MM4, R_ESP, R_SP, R_AH, R_XMM4, R_NO, R_NO, R_NO,
  949. R_MM5, R_EBP, R_BP, R_CH, R_XMM5, R_NO, R_NO, R_NO,
  950. R_MM6, R_ESI, R_SI, R_DH, R_XMM6, R_NO, R_NO, R_NO,
  951. R_MM7, R_EDI, R_DI, R_BH, R_XMM7, R_NO, R_NO, R_NO
  952. );
  953. var
  954. j : longint;
  955. i,b : tregister;
  956. sym : pasmsymbol;
  957. md,s : byte;
  958. base,index,scalefactor,
  959. o : longint;
  960. begin
  961. process_ea:=false;
  962. { register ? }
  963. if (input.typ=top_reg) then
  964. begin
  965. j:=0;
  966. while (j<=high(regs)) do
  967. begin
  968. if input.reg=regs[j] then
  969. break;
  970. inc(j);
  971. end;
  972. if j<=high(regs) then
  973. begin
  974. output.sib_present:=false;
  975. output.bytes:=0;
  976. output.modrm:=$c0 or (rfield shl 3) or (j shr 3);
  977. output.size:=1;
  978. process_ea:=true;
  979. end;
  980. exit;
  981. end;
  982. { memory reference }
  983. i:=input.ref^.index;
  984. b:=input.ref^.base;
  985. s:=input.ref^.scalefactor;
  986. o:=input.ref^.offset;
  987. sym:=input.ref^.symbol;
  988. { it's direct address }
  989. if (b=R_NO) and (i=R_NO) then
  990. begin
  991. { it's a pure offset }
  992. output.sib_present:=false;
  993. output.bytes:=4;
  994. output.modrm:=5 or (rfield shl 3);
  995. end
  996. else
  997. { it's an indirection }
  998. begin
  999. { 16 bit address? }
  1000. if not((i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) and
  1001. (b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI])) then
  1002. Message(asmw_e_16bit_not_supported);
  1003. {$ifdef OPTEA}
  1004. { make single reg base }
  1005. if (b=R_NO) and (s=1) then
  1006. begin
  1007. b:=i;
  1008. i:=R_NO;
  1009. end;
  1010. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  1011. if (b=R_NO) and
  1012. (((s=2) and (i<>R_ESP)) or
  1013. (s=3) or (s=5) or (s=9)) then
  1014. begin
  1015. b:=i;
  1016. dec(s);
  1017. end;
  1018. { swap ESP into base if scalefactor is 1 }
  1019. if (s=1) and (i=R_ESP) then
  1020. begin
  1021. i:=b;
  1022. b:=R_ESP;
  1023. end;
  1024. {$endif}
  1025. { wrong, for various reasons }
  1026. if (i=R_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (i<>R_NO)) then
  1027. exit;
  1028. { base }
  1029. case b of
  1030. R_EAX : base:=0;
  1031. R_ECX : base:=1;
  1032. R_EDX : base:=2;
  1033. R_EBX : base:=3;
  1034. R_ESP : base:=4;
  1035. R_NO,
  1036. R_EBP : base:=5;
  1037. R_ESI : base:=6;
  1038. R_EDI : base:=7;
  1039. else
  1040. exit;
  1041. end;
  1042. { index }
  1043. case i of
  1044. R_EAX : index:=0;
  1045. R_ECX : index:=1;
  1046. R_EDX : index:=2;
  1047. R_EBX : index:=3;
  1048. R_NO : index:=4;
  1049. R_EBP : index:=5;
  1050. R_ESI : index:=6;
  1051. R_EDI : index:=7;
  1052. else
  1053. exit;
  1054. end;
  1055. case s of
  1056. 0,
  1057. 1 : scalefactor:=0;
  1058. 2 : scalefactor:=1;
  1059. 4 : scalefactor:=2;
  1060. 8 : scalefactor:=3;
  1061. else
  1062. exit;
  1063. end;
  1064. if (b=R_NO) or
  1065. ((b<>R_EBP) and (o=0) and (sym=nil)) then
  1066. md:=0
  1067. else
  1068. if ((o>=-128) and (o<=127) and (sym=nil)) then
  1069. md:=1
  1070. else
  1071. md:=2;
  1072. if (b=R_NO) or (md=2) then
  1073. output.bytes:=4
  1074. else
  1075. output.bytes:=md;
  1076. { SIB needed ? }
  1077. if (i=R_NO) and (b<>R_ESP) then
  1078. begin
  1079. output.sib_present:=false;
  1080. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1081. end
  1082. else
  1083. begin
  1084. output.sib_present:=true;
  1085. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1086. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1087. end;
  1088. end;
  1089. if output.sib_present then
  1090. output.size:=2+output.bytes
  1091. else
  1092. output.size:=1+output.bytes;
  1093. process_ea:=true;
  1094. end;
  1095. function taicpu.calcsize(p:PInsEntry):longint;
  1096. var
  1097. codes : pchar;
  1098. c : byte;
  1099. len : longint;
  1100. ea_data : ea;
  1101. begin
  1102. len:=0;
  1103. codes:=@p^.code;
  1104. repeat
  1105. c:=ord(codes^);
  1106. inc(codes);
  1107. case c of
  1108. 0 :
  1109. break;
  1110. 1,2,3 :
  1111. begin
  1112. inc(codes,c);
  1113. inc(len,c);
  1114. end;
  1115. 8,9,10 :
  1116. begin
  1117. inc(codes);
  1118. inc(len);
  1119. end;
  1120. 4,5,6,7 :
  1121. begin
  1122. if opsize=S_W then
  1123. inc(len,2)
  1124. else
  1125. inc(len);
  1126. end;
  1127. 15,
  1128. 12,13,14,
  1129. 16,17,18,
  1130. 20,21,22,
  1131. 40,41,42 :
  1132. inc(len);
  1133. 24,25,26,
  1134. 31,
  1135. 48,49,50 :
  1136. inc(len,2);
  1137. 28,29,30, { we don't have 16 bit immediates code }
  1138. 32,33,34,
  1139. 52,53,54,
  1140. 56,57,58 :
  1141. inc(len,4);
  1142. 192,193,194 :
  1143. if NeedAddrPrefix(c-192) then
  1144. inc(len);
  1145. 208 :
  1146. inc(len);
  1147. 200,
  1148. 201,
  1149. 202,
  1150. 209,
  1151. 210,
  1152. 217,218,219 : ;
  1153. 216 :
  1154. begin
  1155. inc(codes);
  1156. inc(len);
  1157. end;
  1158. 224,225,226 :
  1159. begin
  1160. InternalError(777002);
  1161. end;
  1162. else
  1163. begin
  1164. if (c>=64) and (c<=191) then
  1165. begin
  1166. if not process_ea(oper[(c shr 3) and 7], ea_data, 0) then
  1167. Message(asmw_e_invalid_effective_address)
  1168. else
  1169. inc(len,ea_data.size);
  1170. end
  1171. else
  1172. InternalError(777003);
  1173. end;
  1174. end;
  1175. until false;
  1176. calcsize:=len;
  1177. end;
  1178. procedure taicpu.GenCode;
  1179. {
  1180. * the actual codes (C syntax, i.e. octal):
  1181. * \0 - terminates the code. (Unless it's a literal of course.)
  1182. * \1, \2, \3 - that many literal bytes follow in the code stream
  1183. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  1184. * (POP is never used for CS) depending on operand 0
  1185. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  1186. * on operand 0
  1187. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  1188. * to the register value of operand 0, 1 or 2
  1189. * \17 - encodes the literal byte 0. (Some compilers don't take
  1190. * kindly to a zero byte in the _middle_ of a compile time
  1191. * string constant, so I had to put this hack in.)
  1192. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  1193. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  1194. * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  1195. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  1196. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  1197. * assembly mode or the address-size override on the operand
  1198. * \37 - a word constant, from the _segment_ part of operand 0
  1199. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  1200. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  1201. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  1202. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  1203. * assembly mode or the address-size override on the operand
  1204. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  1205. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  1206. * field the register value of operand b.
  1207. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  1208. * field equal to digit b.
  1209. * \30x - might be an 0x67 byte, depending on the address size of
  1210. * the memory reference in operand x.
  1211. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  1212. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  1213. * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  1214. * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  1215. * \322 - indicates that this instruction is only valid when the
  1216. * operand size is the default (instruction to disassembler,
  1217. * generates no code in the assembler)
  1218. * \330 - a literal byte follows in the code stream, to be added
  1219. * to the condition code value of the instruction.
  1220. * \340 - reserve <operand 0> bytes of uninitialised storage.
  1221. * Operand 0 had better be a segmentless constant.
  1222. }
  1223. var
  1224. currval : longint;
  1225. currsym : pasmsymbol;
  1226. procedure getvalsym(opidx:longint);
  1227. begin
  1228. case oper[opidx].typ of
  1229. top_ref :
  1230. begin
  1231. currval:=oper[opidx].ref^.offset;
  1232. currsym:=oper[opidx].ref^.symbol;
  1233. end;
  1234. top_const :
  1235. begin
  1236. currval:=oper[opidx].val;
  1237. currsym:=nil;
  1238. end;
  1239. top_symbol :
  1240. begin
  1241. currval:=oper[opidx].symofs;
  1242. currsym:=oper[opidx].sym;
  1243. end;
  1244. else
  1245. Message(asmw_e_immediate_or_reference_expected);
  1246. end;
  1247. end;
  1248. const
  1249. CondVal:array[TAsmCond] of byte=($0,
  1250. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  1251. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  1252. $0, $A, $A, $B, $8, $4);
  1253. var
  1254. c : byte;
  1255. pb,
  1256. codes : pchar;
  1257. bytes : array[0..3] of byte;
  1258. rfield,
  1259. data,s,opidx : longint;
  1260. ea_data : ea;
  1261. begin
  1262. codes:=insentry^.code;
  1263. { Force word push/pop for registers }
  1264. if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
  1265. ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
  1266. begin
  1267. bytes[0]:=$66;
  1268. objectoutput^.writebytes(bytes,1);
  1269. end;
  1270. repeat
  1271. c:=ord(codes^);
  1272. inc(codes);
  1273. case c of
  1274. 0 :
  1275. break;
  1276. 1,2,3 :
  1277. begin
  1278. objectoutput^.writebytes(codes^,c);
  1279. inc(codes,c);
  1280. end;
  1281. 4,6 :
  1282. begin
  1283. case oper[0].reg of
  1284. R_CS :
  1285. begin
  1286. if c=4 then
  1287. bytes[0]:=$f
  1288. else
  1289. bytes[0]:=$e;
  1290. end;
  1291. R_NO,
  1292. R_DS :
  1293. begin
  1294. if c=4 then
  1295. bytes[0]:=$1f
  1296. else
  1297. bytes[0]:=$1e;
  1298. end;
  1299. R_ES :
  1300. begin
  1301. if c=4 then
  1302. bytes[0]:=$7
  1303. else
  1304. bytes[0]:=$6;
  1305. end;
  1306. R_SS :
  1307. begin
  1308. if c=4 then
  1309. bytes[0]:=$17
  1310. else
  1311. bytes[0]:=$16;
  1312. end;
  1313. else
  1314. InternalError(777004);
  1315. end;
  1316. objectoutput^.writebytes(bytes,1);
  1317. end;
  1318. 5,7 :
  1319. begin
  1320. case oper[0].reg of
  1321. R_FS :
  1322. begin
  1323. if c=5 then
  1324. bytes[0]:=$a1
  1325. else
  1326. bytes[0]:=$a0;
  1327. end;
  1328. R_GS :
  1329. begin
  1330. if c=5 then
  1331. bytes[0]:=$a9
  1332. else
  1333. bytes[0]:=$a8;
  1334. end;
  1335. else
  1336. InternalError(777005);
  1337. end;
  1338. objectoutput^.writebytes(bytes,1);
  1339. end;
  1340. 8,9,10 :
  1341. begin
  1342. bytes[0]:=ord(codes^)+regval(oper[c-8].reg);
  1343. inc(codes);
  1344. objectoutput^.writebytes(bytes,1);
  1345. end;
  1346. 15 :
  1347. begin
  1348. bytes[0]:=0;
  1349. objectoutput^.writebytes(bytes,1);
  1350. end;
  1351. 12,13,14 :
  1352. begin
  1353. getvalsym(c-12);
  1354. if (currval<-128) or (currval>127) then
  1355. Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
  1356. if assigned(currsym) then
  1357. objectoutput^.writereloc(currval,1,currsym,relative_false)
  1358. else
  1359. objectoutput^.writebytes(currval,1);
  1360. end;
  1361. 16,17,18 :
  1362. begin
  1363. getvalsym(c-16);
  1364. if (currval<-256) or (currval>255) then
  1365. Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
  1366. if assigned(currsym) then
  1367. objectoutput^.writereloc(currval,1,currsym,relative_false)
  1368. else
  1369. objectoutput^.writebytes(currval,1);
  1370. end;
  1371. 20,21,22 :
  1372. begin
  1373. getvalsym(c-20);
  1374. if (currval<0) or (currval>255) then
  1375. Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
  1376. if assigned(currsym) then
  1377. objectoutput^.writereloc(currval,1,currsym,relative_false)
  1378. else
  1379. objectoutput^.writebytes(currval,1);
  1380. end;
  1381. 24,25,26 :
  1382. begin
  1383. getvalsym(c-24);
  1384. if (currval<-65536) or (currval>65535) then
  1385. Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
  1386. if assigned(currsym) then
  1387. objectoutput^.writereloc(currval,2,currsym,relative_false)
  1388. else
  1389. objectoutput^.writebytes(currval,2);
  1390. end;
  1391. 28,29,30 :
  1392. begin
  1393. getvalsym(c-28);
  1394. if assigned(currsym) then
  1395. objectoutput^.writereloc(currval,4,currsym,relative_false)
  1396. else
  1397. objectoutput^.writebytes(currval,4);
  1398. end;
  1399. 32,33,34 :
  1400. begin
  1401. getvalsym(c-32);
  1402. if assigned(currsym) then
  1403. objectoutput^.writereloc(currval,4,currsym,relative_false)
  1404. else
  1405. objectoutput^.writebytes(currval,4);
  1406. end;
  1407. 40,41,42 :
  1408. begin
  1409. getvalsym(c-40);
  1410. data:=currval-insend;
  1411. if assigned(currsym) then
  1412. inc(data,currsym^.address);
  1413. if (data>127) or (data<-128) then
  1414. Message1(asmw_e_short_jmp_out_of_range,tostr(data));
  1415. objectoutput^.writebytes(data,1);
  1416. end;
  1417. 52,53,54 :
  1418. begin
  1419. getvalsym(c-52);
  1420. if assigned(currsym) then
  1421. objectoutput^.writereloc(currval,4,currsym,relative_true)
  1422. else
  1423. objectoutput^.writereloc(currval-insend,4,nil,relative_false)
  1424. end;
  1425. 56,57,58 :
  1426. begin
  1427. getvalsym(c-56);
  1428. if assigned(currsym) then
  1429. objectoutput^.writereloc(currval,4,currsym,relative_true)
  1430. else
  1431. objectoutput^.writereloc(currval-insend,4,nil,relative_false)
  1432. end;
  1433. 192,193,194 :
  1434. begin
  1435. if NeedAddrPrefix(c-192) then
  1436. begin
  1437. bytes[0]:=$67;
  1438. objectoutput^.writebytes(bytes,1);
  1439. end;
  1440. end;
  1441. 200 :
  1442. begin
  1443. bytes[0]:=$67;
  1444. objectoutput^.writebytes(bytes,1);
  1445. end;
  1446. 208 :
  1447. begin
  1448. bytes[0]:=$66;
  1449. objectoutput^.writebytes(bytes,1);
  1450. end;
  1451. 216 :
  1452. begin
  1453. bytes[0]:=ord(codes^)+condval[condition];
  1454. inc(codes);
  1455. objectoutput^.writebytes(bytes,1);
  1456. end;
  1457. 201,
  1458. 202,
  1459. 209,
  1460. 210,
  1461. 217,218,219 :
  1462. begin
  1463. { these are dissambler hints or 32 bit prefixes which
  1464. are not needed }
  1465. end;
  1466. 31,
  1467. 48,49,50,
  1468. 224,225,226 :
  1469. begin
  1470. InternalError(777006);
  1471. end
  1472. else
  1473. begin
  1474. if (c>=64) and (c<=191) then
  1475. begin
  1476. if (c<127) then
  1477. begin
  1478. if (oper[c and 7].typ=top_reg) then
  1479. rfield:=regval(oper[c and 7].reg)
  1480. else
  1481. rfield:=regval(oper[c and 7].ref^.base);
  1482. end
  1483. else
  1484. rfield:=c and 7;
  1485. opidx:=(c shr 3) and 7;
  1486. if not process_ea(oper[opidx], ea_data, rfield) then
  1487. Message(asmw_e_invalid_effective_address);
  1488. pb:=@bytes;
  1489. pb^:=chr(ea_data.modrm);
  1490. inc(pb);
  1491. if ea_data.sib_present then
  1492. begin
  1493. pb^:=chr(ea_data.sib);
  1494. inc(pb);
  1495. end;
  1496. s:=pb-pchar(@bytes);
  1497. objectoutput^.writebytes(bytes,s);
  1498. case ea_data.bytes of
  1499. 0 : ;
  1500. 1 :
  1501. begin
  1502. if (oper[opidx].ot and OT_MEMORY)=OT_MEMORY then
  1503. objectoutput^.writereloc(oper[opidx].ref^.offset,1,oper[opidx].ref^.symbol,relative_false)
  1504. else
  1505. begin
  1506. bytes[0]:=oper[opidx].ref^.offset;
  1507. objectoutput^.writebytes(bytes,1);
  1508. end;
  1509. inc(s);
  1510. end;
  1511. 2,4 :
  1512. begin
  1513. objectoutput^.writereloc(oper[opidx].ref^.offset,ea_data.bytes,
  1514. oper[opidx].ref^.symbol,relative_false);
  1515. inc(s,ea_data.bytes);
  1516. end;
  1517. end;
  1518. end
  1519. else
  1520. InternalError(777007);
  1521. end;
  1522. end;
  1523. until false;
  1524. end;
  1525. {$endif NOAG386BIN}
  1526. end.
  1527. {
  1528. $Log$
  1529. Revision 1.2 2000-10-15 10:50:46 florian
  1530. * fixed xmm register access
  1531. Revision 1.1 2000/10/15 09:39:37 peter
  1532. * moved cpu*.pas to i386/
  1533. * renamed n386 to common cpunode
  1534. Revision 1.5 2000/09/24 15:06:14 peter
  1535. * use defines.inc
  1536. Revision 1.4 2000/08/27 16:11:50 peter
  1537. * moved some util functions from globals,cobjects to cutils
  1538. * splitted files into finput,fmodule
  1539. Revision 1.3 2000/07/13 12:08:25 michael
  1540. + patched to 1.1.0 with former 1.09patch from peter
  1541. Revision 1.2 2000/07/13 11:32:38 michael
  1542. + removed logs
  1543. }