i386asm.pas 44 KB

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