i386asm.pas 44 KB

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