cpuasm.pas 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849
  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. 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 : tasmsymbol);
  79. constructor op_sym(op : tasmop;_size : topsize;_op1 : tasmsymbol);
  80. constructor op_sym_ofs(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint);
  81. constructor op_sym_ofs_reg(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : tregister);
  82. constructor op_sym_ofs_ref(op : tasmop;_size : topsize;_op1 : tasmsymbol;_op1ofs:longint;_op2 : preference);
  83. procedure loadconst(opidx:longint;l:longint);
  84. procedure loadsymbol(opidx:longint;s:tasmsymbol;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 Swatoperands;
  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:tasmsymbol;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 : tasmsymbol);
  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 : tasmsymbol);
  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 : tasmsymbol;_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 : tasmsymbol;_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 : tasmsymbol;_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(tasmsymbol(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.Swatoperands;
  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. Swatoperands;
  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. if (ot and OT_SIZE_MASK)=0 then
  683. ot:=OT_MEMORY or opsize_2_type[i,opsize]
  684. else
  685. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  686. if (ref^.base=R_NO) and (ref^.index=R_NO) then
  687. ot:=ot or OT_MEM_OFFS;
  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. { we can leave because the size for all operands is forced to be
  809. the same
  810. but not if IF_SB IF_SW or IF_SD is set PM }
  811. if asize=-1 then
  812. exit;
  813. siz[0]:=asize;
  814. siz[1]:=asize;
  815. siz[2]:=asize;
  816. end;
  817. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  818. begin
  819. if (p^.flags and IF_SM2)<>0 then
  820. oprs:=2
  821. else
  822. oprs:=p^.ops;
  823. for i:=0 to oprs-1 do
  824. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  825. begin
  826. for j:=0 to oprs-1 do
  827. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  828. break;
  829. end;
  830. end
  831. else
  832. oprs:=2;
  833. { Check operand sizes }
  834. for i:=0 to p^.ops-1 do
  835. begin
  836. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  837. ((oper[i].ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  838. { Immediates can always include smaller size }
  839. ((oper[i].ot and OT_IMMEDIATE)=0) and
  840. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i].ot and OT_SIZE_MASK)) then
  841. Matches:=2;
  842. end;
  843. end;
  844. procedure taicpu.ResetPass2;
  845. begin
  846. { we are here in a second pass, check if the instruction can be optimized }
  847. if assigned(InsEntry) and
  848. ((InsEntry^.flags and IF_PASS2)<>0) then
  849. begin
  850. InsEntry:=nil;
  851. InsSize:=0;
  852. end;
  853. LastInsOffset:=-1;
  854. end;
  855. function taicpu.CheckIfValid:boolean;
  856. var
  857. m,i : longint;
  858. begin
  859. CheckIfValid:=false;
  860. { Things which may only be done once, not when a second pass is done to
  861. optimize }
  862. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  863. begin
  864. { We need intel style operands }
  865. SetOperandOrder(op_intel);
  866. { create the .ot fields }
  867. create_ot;
  868. { set the file postion }
  869. aktfilepos:=fileinfo;
  870. end
  871. else
  872. begin
  873. { we've already an insentry so it's valid }
  874. CheckIfValid:=true;
  875. exit;
  876. end;
  877. { Lookup opcode in the table }
  878. InsSize:=-1;
  879. i:=instabcache^[opcode];
  880. if i=-1 then
  881. begin
  882. {$ifdef TP}
  883. Message1(asmw_e_opcode_not_in_table,'');
  884. {$else}
  885. Message1(asmw_e_opcode_not_in_table,att_op2str[opcode]);
  886. {$endif}
  887. exit;
  888. end;
  889. insentry:=@instab[i];
  890. while (insentry^.opcode=opcode) do
  891. begin
  892. m:=matches(insentry);
  893. if m=100 then
  894. begin
  895. InsSize:=calcsize(insentry);
  896. if (segprefix<>R_NO) then
  897. inc(InsSize);
  898. { For opsize if size if forced }
  899. if (insentry^.flags and (IF_SB or IF_SW or IF_SD))<>0 then
  900. begin
  901. if (insentry^.flags and IF_ARMASK)=0 then
  902. begin
  903. if (insentry^.flags and IF_SB)<>0 then
  904. begin
  905. if opsize=S_NO then
  906. opsize:=S_B;
  907. end
  908. else if (insentry^.flags and IF_SW)<>0 then
  909. begin
  910. if opsize=S_NO then
  911. opsize:=S_W;
  912. end
  913. else if (insentry^.flags and IF_SD)<>0 then
  914. begin
  915. if opsize=S_NO then
  916. opsize:=S_L;
  917. end;
  918. end;
  919. end;
  920. CheckIfValid:=true;
  921. exit;
  922. end;
  923. inc(i);
  924. insentry:=@instab[i];
  925. end;
  926. if insentry^.opcode<>opcode then
  927. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  928. { No instruction found, set insentry to nil and inssize to -1 }
  929. insentry:=nil;
  930. inssize:=-1;
  931. end;
  932. function taicpu.Pass1(offset:longint):longint;
  933. begin
  934. Pass1:=0;
  935. { Save the old offset and set the new offset }
  936. InsOffset:=Offset;
  937. { Things which may only be done once, not when a second pass is done to
  938. optimize }
  939. if Insentry=nil then
  940. begin
  941. { Check if error last time then InsSize=-1 }
  942. if InsSize=-1 then
  943. exit;
  944. { set the file postion }
  945. aktfilepos:=fileinfo;
  946. end
  947. else
  948. begin
  949. {$ifdef PASS2FLAG}
  950. { we are here in a second pass, check if the instruction can be optimized }
  951. if (InsEntry^.flags and IF_PASS2)=0 then
  952. begin
  953. Pass1:=InsSize;
  954. exit;
  955. end;
  956. { update the .ot fields, some top_const can be updated }
  957. create_ot;
  958. {$endif}
  959. end;
  960. { Check if it's a valid instruction }
  961. if CheckIfValid then
  962. begin
  963. LastInsOffset:=InsOffset;
  964. Pass1:=InsSize;
  965. exit;
  966. end;
  967. LastInsOffset:=-1;
  968. end;
  969. procedure taicpu.Pass2;
  970. var
  971. c : longint;
  972. begin
  973. { error in pass1 ? }
  974. if insentry=nil then
  975. exit;
  976. aktfilepos:=fileinfo;
  977. { Segment override }
  978. if (segprefix<>R_NO) then
  979. begin
  980. case segprefix of
  981. R_CS : c:=$2e;
  982. R_DS : c:=$3e;
  983. R_ES : c:=$26;
  984. R_FS : c:=$64;
  985. R_GS : c:=$65;
  986. R_SS : c:=$36;
  987. end;
  988. objectdata.writebytes(c,1);
  989. { fix the offset for GenNode }
  990. inc(InsOffset);
  991. end;
  992. { Generate the instruction }
  993. GenCode;
  994. end;
  995. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  996. var
  997. i,b : tregister;
  998. begin
  999. if (OT_MEMORY and (not oper[opidx].ot))=0 then
  1000. begin
  1001. i:=oper[opidx].ref^.index;
  1002. b:=oper[opidx].ref^.base;
  1003. if not(i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) or
  1004. not(b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) then
  1005. begin
  1006. NeedAddrPrefix:=true;
  1007. exit;
  1008. end;
  1009. end;
  1010. NeedAddrPrefix:=false;
  1011. end;
  1012. function regval(r:tregister):byte;
  1013. begin
  1014. case r of
  1015. R_EAX,R_AX,R_AL,R_ES,R_CR0,R_DR0,R_ST,R_ST0,R_MM0,R_XMM0 :
  1016. regval:=0;
  1017. R_ECX,R_CX,R_CL,R_CS,R_DR1,R_ST1,R_MM1,R_XMM1 :
  1018. regval:=1;
  1019. R_EDX,R_DX,R_DL,R_SS,R_CR2,R_DR2,R_ST2,R_MM2,R_XMM2 :
  1020. regval:=2;
  1021. R_EBX,R_BX,R_BL,R_DS,R_CR3,R_DR3,R_TR3,R_ST3,R_MM3,R_XMM3 :
  1022. regval:=3;
  1023. R_ESP,R_SP,R_AH,R_FS,R_CR4,R_TR4,R_ST4,R_MM4,R_XMM4 :
  1024. regval:=4;
  1025. R_EBP,R_BP,R_CH,R_GS,R_TR5,R_ST5,R_MM5,R_XMM5 :
  1026. regval:=5;
  1027. R_ESI,R_SI,R_DH,R_DR6,R_TR6,R_ST6,R_MM6,R_XMM6 :
  1028. regval:=6;
  1029. R_EDI,R_DI,R_BH,R_DR7,R_TR7,R_ST7,R_MM7,R_XMM7 :
  1030. regval:=7;
  1031. else
  1032. begin
  1033. internalerror(777001);
  1034. regval:=0;
  1035. end;
  1036. end;
  1037. end;
  1038. function process_ea(const input:toper;var output:ea;rfield:longint):boolean;
  1039. const
  1040. regs : array[0..63] of tregister=(
  1041. R_MM0, R_EAX, R_AX, R_AL, R_XMM0, R_NO, R_NO, R_NO,
  1042. R_MM1, R_ECX, R_CX, R_CL, R_XMM1, R_NO, R_NO, R_NO,
  1043. R_MM2, R_EDX, R_DX, R_DL, R_XMM2, R_NO, R_NO, R_NO,
  1044. R_MM3, R_EBX, R_BX, R_BL, R_XMM3, R_NO, R_NO, R_NO,
  1045. R_MM4, R_ESP, R_SP, R_AH, R_XMM4, R_NO, R_NO, R_NO,
  1046. R_MM5, R_EBP, R_BP, R_CH, R_XMM5, R_NO, R_NO, R_NO,
  1047. R_MM6, R_ESI, R_SI, R_DH, R_XMM6, R_NO, R_NO, R_NO,
  1048. R_MM7, R_EDI, R_DI, R_BH, R_XMM7, R_NO, R_NO, R_NO
  1049. );
  1050. var
  1051. j : longint;
  1052. i,b : tregister;
  1053. sym : tasmsymbol;
  1054. md,s : byte;
  1055. base,index,scalefactor,
  1056. o : longint;
  1057. begin
  1058. process_ea:=false;
  1059. { register ? }
  1060. if (input.typ=top_reg) then
  1061. begin
  1062. j:=0;
  1063. while (j<=high(regs)) do
  1064. begin
  1065. if input.reg=regs[j] then
  1066. break;
  1067. inc(j);
  1068. end;
  1069. if j<=high(regs) then
  1070. begin
  1071. output.sib_present:=false;
  1072. output.bytes:=0;
  1073. output.modrm:=$c0 or (rfield shl 3) or (j shr 3);
  1074. output.size:=1;
  1075. process_ea:=true;
  1076. end;
  1077. exit;
  1078. end;
  1079. { memory reference }
  1080. i:=input.ref^.index;
  1081. b:=input.ref^.base;
  1082. s:=input.ref^.scalefactor;
  1083. o:=input.ref^.offset+input.ref^.offsetfixup;
  1084. sym:=input.ref^.symbol;
  1085. { it's direct address }
  1086. if (b=R_NO) and (i=R_NO) then
  1087. begin
  1088. { it's a pure offset }
  1089. output.sib_present:=false;
  1090. output.bytes:=4;
  1091. output.modrm:=5 or (rfield shl 3);
  1092. end
  1093. else
  1094. { it's an indirection }
  1095. begin
  1096. { 16 bit address? }
  1097. if not((i in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI]) and
  1098. (b in [R_NO,R_EAX,R_EBX,R_ECX,R_EDX,R_EBP,R_ESP,R_ESI,R_EDI])) then
  1099. Message(asmw_e_16bit_not_supported);
  1100. {$ifdef OPTEA}
  1101. { make single reg base }
  1102. if (b=R_NO) and (s=1) then
  1103. begin
  1104. b:=i;
  1105. i:=R_NO;
  1106. end;
  1107. { convert [3,5,9]*EAX to EAX+[2,4,8]*EAX }
  1108. if (b=R_NO) and
  1109. (((s=2) and (i<>R_ESP)) or
  1110. (s=3) or (s=5) or (s=9)) then
  1111. begin
  1112. b:=i;
  1113. dec(s);
  1114. end;
  1115. { swap ESP into base if scalefactor is 1 }
  1116. if (s=1) and (i=R_ESP) then
  1117. begin
  1118. i:=b;
  1119. b:=R_ESP;
  1120. end;
  1121. {$endif}
  1122. { wrong, for various reasons }
  1123. if (i=R_ESP) or ((s<>1) and (s<>2) and (s<>4) and (s<>8) and (i<>R_NO)) then
  1124. exit;
  1125. { base }
  1126. case b of
  1127. R_EAX : base:=0;
  1128. R_ECX : base:=1;
  1129. R_EDX : base:=2;
  1130. R_EBX : base:=3;
  1131. R_ESP : base:=4;
  1132. R_NO,
  1133. R_EBP : base:=5;
  1134. R_ESI : base:=6;
  1135. R_EDI : base:=7;
  1136. else
  1137. exit;
  1138. end;
  1139. { index }
  1140. case i of
  1141. R_EAX : index:=0;
  1142. R_ECX : index:=1;
  1143. R_EDX : index:=2;
  1144. R_EBX : index:=3;
  1145. R_NO : index:=4;
  1146. R_EBP : index:=5;
  1147. R_ESI : index:=6;
  1148. R_EDI : index:=7;
  1149. else
  1150. exit;
  1151. end;
  1152. case s of
  1153. 0,
  1154. 1 : scalefactor:=0;
  1155. 2 : scalefactor:=1;
  1156. 4 : scalefactor:=2;
  1157. 8 : scalefactor:=3;
  1158. else
  1159. exit;
  1160. end;
  1161. if (b=R_NO) or
  1162. ((b<>R_EBP) and (o=0) and (sym=nil)) then
  1163. md:=0
  1164. else
  1165. if ((o>=-128) and (o<=127) and (sym=nil)) then
  1166. md:=1
  1167. else
  1168. md:=2;
  1169. if (b=R_NO) or (md=2) then
  1170. output.bytes:=4
  1171. else
  1172. output.bytes:=md;
  1173. { SIB needed ? }
  1174. if (i=R_NO) and (b<>R_ESP) then
  1175. begin
  1176. output.sib_present:=false;
  1177. output.modrm:=(md shl 6) or (rfield shl 3) or base;
  1178. end
  1179. else
  1180. begin
  1181. output.sib_present:=true;
  1182. output.modrm:=(md shl 6) or (rfield shl 3) or 4;
  1183. output.sib:=(scalefactor shl 6) or (index shl 3) or base;
  1184. end;
  1185. end;
  1186. if output.sib_present then
  1187. output.size:=2+output.bytes
  1188. else
  1189. output.size:=1+output.bytes;
  1190. process_ea:=true;
  1191. end;
  1192. function taicpu.calcsize(p:PInsEntry):longint;
  1193. var
  1194. codes : pchar;
  1195. c : byte;
  1196. len : longint;
  1197. ea_data : ea;
  1198. begin
  1199. len:=0;
  1200. codes:=@p^.code;
  1201. repeat
  1202. c:=ord(codes^);
  1203. inc(codes);
  1204. case c of
  1205. 0 :
  1206. break;
  1207. 1,2,3 :
  1208. begin
  1209. inc(codes,c);
  1210. inc(len,c);
  1211. end;
  1212. 8,9,10 :
  1213. begin
  1214. inc(codes);
  1215. inc(len);
  1216. end;
  1217. 4,5,6,7 :
  1218. begin
  1219. if opsize=S_W then
  1220. inc(len,2)
  1221. else
  1222. inc(len);
  1223. end;
  1224. 15,
  1225. 12,13,14,
  1226. 16,17,18,
  1227. 20,21,22,
  1228. 40,41,42 :
  1229. inc(len);
  1230. 24,25,26,
  1231. 31,
  1232. 48,49,50 :
  1233. inc(len,2);
  1234. 28,29,30, { we don't have 16 bit immediates code }
  1235. 32,33,34,
  1236. 52,53,54,
  1237. 56,57,58 :
  1238. inc(len,4);
  1239. 192,193,194 :
  1240. if NeedAddrPrefix(c-192) then
  1241. inc(len);
  1242. 208 :
  1243. inc(len);
  1244. 200,
  1245. 201,
  1246. 202,
  1247. 209,
  1248. 210,
  1249. 217,218,219 : ;
  1250. 216 :
  1251. begin
  1252. inc(codes);
  1253. inc(len);
  1254. end;
  1255. 224,225,226 :
  1256. begin
  1257. InternalError(777002);
  1258. end;
  1259. else
  1260. begin
  1261. if (c>=64) and (c<=191) then
  1262. begin
  1263. if not process_ea(oper[(c shr 3) and 7], ea_data, 0) then
  1264. Message(asmw_e_invalid_effective_address)
  1265. else
  1266. inc(len,ea_data.size);
  1267. end
  1268. else
  1269. InternalError(777003);
  1270. end;
  1271. end;
  1272. until false;
  1273. calcsize:=len;
  1274. end;
  1275. procedure taicpu.GenCode;
  1276. {
  1277. * the actual codes (C syntax, i.e. octal):
  1278. * \0 - terminates the code. (Unless it's a literal of course.)
  1279. * \1, \2, \3 - that many literal bytes follow in the code stream
  1280. * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  1281. * (POP is never used for CS) depending on operand 0
  1282. * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
  1283. * on operand 0
  1284. * \10, \11, \12 - a literal byte follows in the code stream, to be added
  1285. * to the register value of operand 0, 1 or 2
  1286. * \17 - encodes the literal byte 0. (Some compilers don't take
  1287. * kindly to a zero byte in the _middle_ of a compile time
  1288. * string constant, so I had to put this hack in.)
  1289. * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  1290. * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  1291. * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  1292. * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  1293. * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  1294. * assembly mode or the address-size override on the operand
  1295. * \37 - a word constant, from the _segment_ part of operand 0
  1296. * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  1297. * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  1298. * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  1299. * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  1300. * assembly mode or the address-size override on the operand
  1301. * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  1302. * \1ab - a ModRM, calculated on EA in operand a, with the spare
  1303. * field the register value of operand b.
  1304. * \2ab - a ModRM, calculated on EA in operand a, with the spare
  1305. * field equal to digit b.
  1306. * \30x - might be an 0x67 byte, depending on the address size of
  1307. * the memory reference in operand x.
  1308. * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
  1309. * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
  1310. * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
  1311. * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
  1312. * \322 - indicates that this instruction is only valid when the
  1313. * operand size is the default (instruction to disassembler,
  1314. * generates no code in the assembler)
  1315. * \330 - a literal byte follows in the code stream, to be added
  1316. * to the condition code value of the instruction.
  1317. * \340 - reserve <operand 0> bytes of uninitialised storage.
  1318. * Operand 0 had better be a segmentless constant.
  1319. }
  1320. var
  1321. currval : longint;
  1322. currsym : tasmsymbol;
  1323. procedure getvalsym(opidx:longint);
  1324. begin
  1325. case oper[opidx].typ of
  1326. top_ref :
  1327. begin
  1328. currval:=oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup;
  1329. currsym:=oper[opidx].ref^.symbol;
  1330. end;
  1331. top_const :
  1332. begin
  1333. currval:=oper[opidx].val;
  1334. currsym:=nil;
  1335. end;
  1336. top_symbol :
  1337. begin
  1338. currval:=oper[opidx].symofs;
  1339. currsym:=oper[opidx].sym;
  1340. end;
  1341. else
  1342. Message(asmw_e_immediate_or_reference_expected);
  1343. end;
  1344. end;
  1345. const
  1346. CondVal:array[TAsmCond] of byte=($0,
  1347. $7, $3, $2, $6, $2, $4, $F, $D, $C, $E, $6, $2,
  1348. $3, $7, $3, $5, $E, $C, $D, $F, $1, $B, $9, $5,
  1349. $0, $A, $A, $B, $8, $4);
  1350. var
  1351. c : byte;
  1352. pb,
  1353. codes : pchar;
  1354. bytes : array[0..3] of byte;
  1355. rfield,
  1356. data,s,opidx : longint;
  1357. ea_data : ea;
  1358. begin
  1359. codes:=insentry^.code;
  1360. { Force word push/pop for registers }
  1361. if (opsize=S_W) and ((codes[0]=#4) or (codes[0]=#6) or
  1362. ((codes[0]=#1) and ((codes[2]=#5) or (codes[2]=#7)))) then
  1363. begin
  1364. bytes[0]:=$66;
  1365. objectdata.writebytes(bytes,1);
  1366. end;
  1367. repeat
  1368. c:=ord(codes^);
  1369. inc(codes);
  1370. case c of
  1371. 0 :
  1372. break;
  1373. 1,2,3 :
  1374. begin
  1375. objectdata.writebytes(codes^,c);
  1376. inc(codes,c);
  1377. end;
  1378. 4,6 :
  1379. begin
  1380. case oper[0].reg of
  1381. R_CS :
  1382. begin
  1383. if c=4 then
  1384. bytes[0]:=$f
  1385. else
  1386. bytes[0]:=$e;
  1387. end;
  1388. R_NO,
  1389. R_DS :
  1390. begin
  1391. if c=4 then
  1392. bytes[0]:=$1f
  1393. else
  1394. bytes[0]:=$1e;
  1395. end;
  1396. R_ES :
  1397. begin
  1398. if c=4 then
  1399. bytes[0]:=$7
  1400. else
  1401. bytes[0]:=$6;
  1402. end;
  1403. R_SS :
  1404. begin
  1405. if c=4 then
  1406. bytes[0]:=$17
  1407. else
  1408. bytes[0]:=$16;
  1409. end;
  1410. else
  1411. InternalError(777004);
  1412. end;
  1413. objectdata.writebytes(bytes,1);
  1414. end;
  1415. 5,7 :
  1416. begin
  1417. case oper[0].reg of
  1418. R_FS :
  1419. begin
  1420. if c=5 then
  1421. bytes[0]:=$a1
  1422. else
  1423. bytes[0]:=$a0;
  1424. end;
  1425. R_GS :
  1426. begin
  1427. if c=5 then
  1428. bytes[0]:=$a9
  1429. else
  1430. bytes[0]:=$a8;
  1431. end;
  1432. else
  1433. InternalError(777005);
  1434. end;
  1435. objectdata.writebytes(bytes,1);
  1436. end;
  1437. 8,9,10 :
  1438. begin
  1439. bytes[0]:=ord(codes^)+regval(oper[c-8].reg);
  1440. inc(codes);
  1441. objectdata.writebytes(bytes,1);
  1442. end;
  1443. 15 :
  1444. begin
  1445. bytes[0]:=0;
  1446. objectdata.writebytes(bytes,1);
  1447. end;
  1448. 12,13,14 :
  1449. begin
  1450. getvalsym(c-12);
  1451. if (currval<-128) or (currval>127) then
  1452. Message2(asmw_e_value_exceeds_bounds,'signed byte',tostr(currval));
  1453. if assigned(currsym) then
  1454. objectdata.writereloc(currval,1,currsym,relative_false)
  1455. else
  1456. objectdata.writebytes(currval,1);
  1457. end;
  1458. 16,17,18 :
  1459. begin
  1460. getvalsym(c-16);
  1461. if (currval<-256) or (currval>255) then
  1462. Message2(asmw_e_value_exceeds_bounds,'byte',tostr(currval));
  1463. if assigned(currsym) then
  1464. objectdata.writereloc(currval,1,currsym,relative_false)
  1465. else
  1466. objectdata.writebytes(currval,1);
  1467. end;
  1468. 20,21,22 :
  1469. begin
  1470. getvalsym(c-20);
  1471. if (currval<0) or (currval>255) then
  1472. Message2(asmw_e_value_exceeds_bounds,'unsigned byte',tostr(currval));
  1473. if assigned(currsym) then
  1474. objectdata.writereloc(currval,1,currsym,relative_false)
  1475. else
  1476. objectdata.writebytes(currval,1);
  1477. end;
  1478. 24,25,26 :
  1479. begin
  1480. getvalsym(c-24);
  1481. if (currval<-65536) or (currval>65535) then
  1482. Message2(asmw_e_value_exceeds_bounds,'word',tostr(currval));
  1483. if assigned(currsym) then
  1484. objectdata.writereloc(currval,2,currsym,relative_false)
  1485. else
  1486. objectdata.writebytes(currval,2);
  1487. end;
  1488. 28,29,30 :
  1489. begin
  1490. getvalsym(c-28);
  1491. if assigned(currsym) then
  1492. objectdata.writereloc(currval,4,currsym,relative_false)
  1493. else
  1494. objectdata.writebytes(currval,4);
  1495. end;
  1496. 32,33,34 :
  1497. begin
  1498. getvalsym(c-32);
  1499. if assigned(currsym) then
  1500. objectdata.writereloc(currval,4,currsym,relative_false)
  1501. else
  1502. objectdata.writebytes(currval,4);
  1503. end;
  1504. 40,41,42 :
  1505. begin
  1506. getvalsym(c-40);
  1507. data:=currval-insend;
  1508. if assigned(currsym) then
  1509. inc(data,currsym.address);
  1510. if (data>127) or (data<-128) then
  1511. Message1(asmw_e_short_jmp_out_of_range,tostr(data));
  1512. objectdata.writebytes(data,1);
  1513. end;
  1514. 52,53,54 :
  1515. begin
  1516. getvalsym(c-52);
  1517. if assigned(currsym) then
  1518. objectdata.writereloc(currval,4,currsym,relative_true)
  1519. else
  1520. objectdata.writereloc(currval-insend,4,nil,relative_false)
  1521. end;
  1522. 56,57,58 :
  1523. begin
  1524. getvalsym(c-56);
  1525. if assigned(currsym) then
  1526. objectdata.writereloc(currval,4,currsym,relative_true)
  1527. else
  1528. objectdata.writereloc(currval-insend,4,nil,relative_false)
  1529. end;
  1530. 192,193,194 :
  1531. begin
  1532. if NeedAddrPrefix(c-192) then
  1533. begin
  1534. bytes[0]:=$67;
  1535. objectdata.writebytes(bytes,1);
  1536. end;
  1537. end;
  1538. 200 :
  1539. begin
  1540. bytes[0]:=$67;
  1541. objectdata.writebytes(bytes,1);
  1542. end;
  1543. 208 :
  1544. begin
  1545. bytes[0]:=$66;
  1546. objectdata.writebytes(bytes,1);
  1547. end;
  1548. 216 :
  1549. begin
  1550. bytes[0]:=ord(codes^)+condval[condition];
  1551. inc(codes);
  1552. objectdata.writebytes(bytes,1);
  1553. end;
  1554. 201,
  1555. 202,
  1556. 209,
  1557. 210,
  1558. 217,218,219 :
  1559. begin
  1560. { these are dissambler hints or 32 bit prefixes which
  1561. are not needed }
  1562. end;
  1563. 31,
  1564. 48,49,50,
  1565. 224,225,226 :
  1566. begin
  1567. InternalError(777006);
  1568. end
  1569. else
  1570. begin
  1571. if (c>=64) and (c<=191) then
  1572. begin
  1573. if (c<127) then
  1574. begin
  1575. if (oper[c and 7].typ=top_reg) then
  1576. rfield:=regval(oper[c and 7].reg)
  1577. else
  1578. rfield:=regval(oper[c and 7].ref^.base);
  1579. end
  1580. else
  1581. rfield:=c and 7;
  1582. opidx:=(c shr 3) and 7;
  1583. if not process_ea(oper[opidx], ea_data, rfield) then
  1584. Message(asmw_e_invalid_effective_address);
  1585. pb:=@bytes;
  1586. pb^:=chr(ea_data.modrm);
  1587. inc(pb);
  1588. if ea_data.sib_present then
  1589. begin
  1590. pb^:=chr(ea_data.sib);
  1591. inc(pb);
  1592. end;
  1593. s:=pb-pchar(@bytes);
  1594. objectdata.writebytes(bytes,s);
  1595. case ea_data.bytes of
  1596. 0 : ;
  1597. 1 :
  1598. begin
  1599. if (oper[opidx].ot and OT_MEMORY)=OT_MEMORY then
  1600. objectdata.writereloc(oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup,1,oper[opidx].ref^.symbol,relative_false)
  1601. else
  1602. begin
  1603. bytes[0]:=oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup;
  1604. objectdata.writebytes(bytes,1);
  1605. end;
  1606. inc(s);
  1607. end;
  1608. 2,4 :
  1609. begin
  1610. objectdata.writereloc(oper[opidx].ref^.offset+oper[opidx].ref^.offsetfixup,ea_data.bytes,
  1611. oper[opidx].ref^.symbol,relative_false);
  1612. inc(s,ea_data.bytes);
  1613. end;
  1614. end;
  1615. end
  1616. else
  1617. InternalError(777007);
  1618. end;
  1619. end;
  1620. until false;
  1621. end;
  1622. {$endif NOAG386BIN}
  1623. end.
  1624. {
  1625. $Log$
  1626. Revision 1.15 2001-04-21 12:13:15 peter
  1627. * restore correct pass2 handling bug 1425 (merged)
  1628. Revision 1.14 2001/04/13 01:22:18 peter
  1629. * symtable change to classes
  1630. * range check generation and errors fixed, make cycle DEBUG=1 works
  1631. * memory leaks fixed
  1632. Revision 1.13 2001/04/05 21:33:45 peter
  1633. * movd and opsize fix merged
  1634. Revision 1.12 2001/03/25 12:29:45 peter
  1635. * offset_fixup fixes (merged)
  1636. Revision 1.11 2001/02/20 21:51:36 peter
  1637. * fpu fixes (merged)
  1638. Revision 1.10 2001/01/13 20:24:24 peter
  1639. * fixed operand order that got mixed up for external writers after
  1640. my previous assembler block valid instruction check
  1641. Revision 1.9 2001/01/12 19:18:42 peter
  1642. * check for valid asm instructions
  1643. Revision 1.8 2001/01/07 15:48:56 jonas
  1644. * references to symbols were only decreased in taicpu.done for jmps, fixed
  1645. Revision 1.7 2000/12/26 15:56:17 peter
  1646. * unrolled loops in taicpu.destroy
  1647. Revision 1.6 2000/12/25 00:07:31 peter
  1648. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1649. tlinkedlist objects)
  1650. Revision 1.5 2000/12/23 19:59:35 peter
  1651. * object to class for ow/og objects
  1652. * split objectdata from objectoutput
  1653. Revision 1.4 2000/12/07 17:19:45 jonas
  1654. * new constant handling: from now on, hex constants >$7fffffff are
  1655. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1656. and became $ffffffff80000000), all constants in the longint range
  1657. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1658. are cardinals and the rest are int64's.
  1659. * added lots of longint typecast to prevent range check errors in the
  1660. compiler and rtl
  1661. * type casts of symbolic ordinal constants are now preserved
  1662. * fixed bug where the original resulttype wasn't restored correctly
  1663. after doing a 64bit rangecheck
  1664. Revision 1.3 2000/11/12 22:20:37 peter
  1665. * create generic toutputsection for binary writers
  1666. Revision 1.2 2000/10/15 10:50:46 florian
  1667. * fixed xmm register access
  1668. Revision 1.1 2000/10/15 09:39:37 peter
  1669. * moved cpu*.pas to i386/
  1670. * renamed n386 to common cpunode
  1671. Revision 1.5 2000/09/24 15:06:14 peter
  1672. * use defines.inc
  1673. Revision 1.4 2000/08/27 16:11:50 peter
  1674. * moved some util functions from globals,cobjects to cutils
  1675. * splitted files into finput,fmodule
  1676. Revision 1.3 2000/07/13 12:08:25 michael
  1677. + patched to 1.1.0 with former 1.09patch from peter
  1678. Revision 1.2 2000/07/13 11:32:38 michael
  1679. + removed logs
  1680. }