cpuasm.pas 44 KB

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