cpuasm.pas 44 KB

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