i386asm.pas 44 KB

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