cpuasm.pas 44 KB

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