cpuasm.pas 49 KB

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