2
0

cpuasm.pas 46 KB

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