mkx86ins.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman and Florian Klaempfl
  3. Convert i386ins.dat from Nasm to a .inc file for usage with
  4. the Free pascal compiler
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. program mkx86ins;
  13. const
  14. Version = '1.6.1';
  15. max_operands = 4;
  16. var
  17. s : string;
  18. i : longint;
  19. i8086 : boolean;
  20. x86_64 : boolean;
  21. function lower(const s : string) : string;
  22. {
  23. return lowercased string of s
  24. }
  25. var
  26. i : longint;
  27. begin
  28. for i:=1 to length(s) do
  29. if s[i] in ['A'..'Z'] then
  30. lower[i]:=char(byte(s[i])+32)
  31. else
  32. lower[i]:=s[i];
  33. lower[0]:=s[0];
  34. end;
  35. function Replace(var s:string;const s1,s2:string):boolean;
  36. var
  37. i : longint;
  38. begin
  39. i:=pos(s1,s);
  40. if i>0 then
  41. begin
  42. Delete(s,i,length(s1));
  43. Insert(s2,s,i);
  44. Replace:=true;
  45. end
  46. else
  47. Replace:=false;
  48. end;
  49. function formatop(s:string;allowsizeonly:boolean):string;
  50. const
  51. replaces=29;
  52. replacetab : array[1..replaces,1..2] of string[32]=(
  53. (':',' or ot_colon'),
  54. ('reg','regnorm'),
  55. ('regmem','rm_gpr'),
  56. ('rm8','rm_gpr or ot_bits8'),
  57. ('rm16','rm_gpr or ot_bits16'),
  58. ('rm32','rm_gpr or ot_bits32'),
  59. ('rm64','rm_gpr or ot_bits64'),
  60. ('rm80','rm_gpr or ot_bits80'),
  61. ('mem8','memory or ot_bits8'),
  62. ('mem16','memory or ot_bits16'),
  63. ('mem32','memory or ot_bits32'),
  64. ('mem64','memory or ot_bits64'),
  65. ('mem128','memory or ot_bits128'),
  66. ('mem256','memory or ot_bits256'),
  67. ('mem512','memory or ot_bits512'),
  68. ('mem80','memory or ot_bits80'),
  69. ('mem','memory'),
  70. ('memory_offs','mem_offs'),
  71. ('imm8','immediate or ot_bits8'),
  72. ('imm16','immediate or ot_bits16'),
  73. ('imm32','immediate or ot_bits32'),
  74. ('imm64','immediate or ot_bits64'),
  75. ('imm80','immediate or ot_bits80'),
  76. ('imm','immediate'),
  77. ('8','bits8'),
  78. ('16','bits16'),
  79. ('32','bits32'),
  80. ('64','bits64'),
  81. ('80','bits80')
  82. );
  83. var
  84. i : longint;
  85. begin
  86. for i:=1to replaces do
  87. begin
  88. if s=replacetab[i,1] then
  89. begin
  90. s:=replacetab[i,2];
  91. break;
  92. end;
  93. end;
  94. formatop:=s;
  95. end;
  96. function readnumber : longint;
  97. var
  98. base : longint;
  99. begin
  100. result:=0;
  101. if s[i]='\' then
  102. begin
  103. base:=8;
  104. inc(i);
  105. if s[i]='x' then
  106. begin
  107. base:=16;
  108. inc(i);
  109. end;
  110. end
  111. else
  112. base:=10;
  113. s[i]:=upcase(s[i]);
  114. while s[i] in ['0'..'9','A'..'F'] do
  115. begin
  116. case s[i] of
  117. '0'..'9':
  118. result:=result*base+ord(s[i])-ord('0');
  119. 'A'..'F':
  120. result:=result*base+ord(s[i])-ord('A')+10;
  121. end;
  122. inc(i);
  123. end;
  124. end;
  125. function tostr(l : longint) : string;
  126. var
  127. hs : string;
  128. begin
  129. str(l,hs);
  130. tostr:=hs;
  131. end;
  132. function readstr : string;
  133. begin
  134. result:='';
  135. while (s[i] in ['0'..'9','A'..'Z','a'..'z','_']) and (i<=length(s)) do
  136. begin
  137. result:=result+s[i];
  138. inc(i);
  139. end;
  140. end;
  141. procedure skipspace;
  142. begin
  143. while (s[i] in [' ',#9]) do
  144. inc(i);
  145. end;
  146. procedure openinc(out f:text;const fn:string);
  147. begin
  148. writeln('creating ',fn);
  149. assign(f,fn);
  150. rewrite(f);
  151. writeln(f,'{ don''t edit, this file is generated from x86ins.dat }');
  152. writeln(f,'(');
  153. end;
  154. procedure closeinc(var f:text);
  155. begin
  156. writeln(f);
  157. writeln(f,');');
  158. close(f);
  159. end;
  160. var
  161. attsuffix,
  162. hs : string;
  163. j : longint;
  164. firstopcode,
  165. first : boolean;
  166. maxinfolen,
  167. code : byte;
  168. insns : longint;
  169. attsuffile,propfile,opfile,
  170. nopfile,attfile,intfile,
  171. infile,insfile : text;
  172. { instruction fields }
  173. skip : boolean;
  174. literalcount,
  175. ops : longint;
  176. intopcode,
  177. attopcode,
  178. opcode,
  179. codes,
  180. flags : string;
  181. optypes : array[1..max_operands] of string;
  182. inschanges: string;
  183. instrwritten: boolean;
  184. SignCheck: Cardinal;
  185. StrSearch: Integer;
  186. const
  187. SIGNED_INT = ' or ot_signed';
  188. procedure DoWriteInstr;
  189. begin
  190. if firstopcode then
  191. firstopcode:=false
  192. else
  193. begin
  194. writeln(opfile,',');
  195. writeln(attfile,',');
  196. writeln(attsuffile,',');
  197. writeln(intfile,',');
  198. writeln(propfile,',');
  199. end;
  200. write(opfile,opcode);
  201. write(intfile,'''',intopcode,'''');
  202. write(attfile,'''',attopcode,'''');
  203. write(attsuffile,attsuffix);
  204. write(propfile,'(Ch: ',inschanges,')');
  205. end;
  206. begin
  207. writeln('Nasm Instruction Table Converter Version ',Version);
  208. i8086:=paramstr(1)='i8086';
  209. x86_64:=paramstr(1)='x86_64';
  210. insns:=0;
  211. maxinfolen:=0;
  212. { open dat file }
  213. assign(infile,'../x86/x86ins.dat');
  214. if x86_64 then
  215. begin
  216. { create inc files }
  217. openinc(insfile,'x8664tab.inc');
  218. openinc(opfile,'x8664op.inc');
  219. assign(nopfile,'x8664nop.inc');
  220. openinc(attfile,'x8664att.inc');
  221. openinc(attsuffile,'x8664ats.inc');
  222. openinc(intfile,'x8664int.inc');
  223. openinc(propfile,'x8664pro.inc');
  224. end
  225. else if i8086 then
  226. begin
  227. { create inc files }
  228. openinc(insfile,'i8086tab.inc');
  229. openinc(opfile,'i8086op.inc');
  230. assign(nopfile,'i8086nop.inc');
  231. openinc(attfile,'i8086att.inc');
  232. openinc(attsuffile,'i8086atts.inc');
  233. openinc(intfile,'i8086int.inc');
  234. openinc(propfile,'i8086prop.inc');
  235. end
  236. else
  237. begin
  238. { create inc files }
  239. openinc(insfile,'i386tab.inc');
  240. openinc(opfile,'i386op.inc');
  241. assign(nopfile,'i386nop.inc');
  242. openinc(attfile,'i386att.inc');
  243. openinc(attsuffile,'i386atts.inc');
  244. openinc(intfile,'i386int.inc');
  245. openinc(propfile,'i386prop.inc');
  246. end;
  247. rewrite(nopfile);
  248. writeln(nopfile,'{ don''t edit, this file is generated from x86ins.dat }');
  249. reset(infile);
  250. first:=true;
  251. opcode:='';
  252. firstopcode:=true;
  253. while not(eof(infile)) do
  254. begin
  255. { handle comment }
  256. readln(infile,s);
  257. while (s[1]=' ') do
  258. delete(s,1,1);
  259. if (s='') or (s[1]=';') then
  260. continue;
  261. if (s[1]='[') then
  262. begin
  263. i:=pos(',',s);
  264. j:=pos(']',s);
  265. if i=0 then
  266. begin
  267. opcode:='A_'+Copy(s,2,j-2);
  268. intopcode:=Copy(s,2,j-2);
  269. { Conditional }
  270. if (intopcode[length(intopcode)]='c') and
  271. (intopcode[length(intopcode)-1]='c') then
  272. dec(byte(intopcode[0]),2);
  273. attopcode:=intopcode;
  274. attsuffix:='attsufNONE';
  275. end
  276. else
  277. begin
  278. SignCheck := 0;
  279. opcode:='A_'+Copy(s,2,i-2);
  280. intopcode:=Copy(s,2,i-2);
  281. { intel conditional }
  282. if (intopcode[length(intopcode)]='c') and
  283. (intopcode[length(intopcode)-1]='c') then
  284. dec(byte(intopcode[0]),2);
  285. attopcode:=Copy(s,i+1,j-i-1);
  286. { att Suffix }
  287. case attopcode[length(attopcode)] of
  288. 'M' :
  289. begin
  290. dec(attopcode[0]);
  291. attsuffix:='attsufMM';
  292. end;
  293. 'N' :
  294. begin
  295. dec(attopcode[0]);
  296. attsuffix:='attsufMMX';
  297. end;
  298. 'X' :
  299. begin
  300. dec(attopcode[0]);
  301. attsuffix:='attsufINT';
  302. end;
  303. 'Y' :
  304. begin
  305. dec(attopcode[0]);
  306. attsuffix:='attsufINTdual';
  307. end;
  308. 'F' :
  309. begin
  310. dec(attopcode[0]);
  311. attsuffix:='attsufFPU';
  312. end;
  313. 'R' :
  314. begin
  315. dec(attopcode[0]);
  316. attsuffix:='attsufFPUint';
  317. end;
  318. else
  319. attsuffix:='attsufNONE';
  320. end;
  321. { att Conditional }
  322. if (attopcode[length(attopcode)]='C') and
  323. (attopcode[length(attopcode)-1]='C') then
  324. dec(byte(attopcode[0]),2);
  325. end;
  326. intopcode:=Lower(intopcode);
  327. attopcode:=Lower(attopcode);
  328. instrwritten:=false;
  329. { read the next line which contains the Change options }
  330. repeat
  331. readln(infile,inschanges);
  332. until eof(infile) or ((inschanges<>'') and (inschanges[1]<>';'));
  333. inschanges[1]:='[';
  334. inschanges[length(inschanges)]:=']';
  335. continue;
  336. end;
  337. { we must have an opcode }
  338. if opcode='' then
  339. runerror(234);
  340. { clear }
  341. ops:=0;
  342. for i:=low(optypes) to high(optypes) do
  343. optypes[i]:='';
  344. codes:='';
  345. flags:='';
  346. skip:=false;
  347. { ops and optypes }
  348. i:=1;
  349. repeat
  350. hs:=readstr;
  351. if (hs='void') or (hs='ignore') then
  352. break;
  353. inc(ops);
  354. optypes[ops]:=optypes[ops]+'ot_'+formatop(hs,false);
  355. while s[i]='|' do
  356. begin
  357. inc(i);
  358. optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr,true);
  359. end;
  360. if s[i] in [',',':'] then
  361. inc(i)
  362. else
  363. break;
  364. until false;
  365. for j:=1 to max_operands-ops do
  366. optypes[max_operands-j+1]:='ot_none';
  367. { codes }
  368. skipspace;
  369. j:=0;
  370. literalcount:=0;
  371. if s[i] in ['\','0'..'9'] then
  372. begin
  373. while not(s[i] in [' ',#9]) do
  374. begin
  375. code:=readnumber;
  376. { for some codes we want also to change the optypes, but not
  377. if the code belongs to a literal sequence }
  378. if (literalcount=0) and (code>=1) and (code<=3) then
  379. literalcount:=code
  380. else
  381. begin
  382. if literalcount>0 then
  383. dec(literalcount)
  384. else
  385. begin
  386. case code of
  387. 12,13,14: {signed byte}
  388. optypes[code-11]:=optypes[code-11]+SIGNED_INT;
  389. 172,173,174: {signed long}
  390. begin
  391. { Addition by J. Gareth "Kit" Moreton }
  392. { See below for workaround for routines that take a 64-bit destination but a 32-bit operand in a non-decorated opcode }
  393. SignCheck := code-171;
  394. optypes[SignCheck]:=optypes[SignCheck]+SIGNED_INT;
  395. end;
  396. end;
  397. end;
  398. end;
  399. codes:=codes+'#'+tostr(code);
  400. inc(j);
  401. end;
  402. end
  403. else
  404. begin
  405. readstr;
  406. codes:='#0';
  407. end;
  408. if j>maxinfolen then
  409. maxinfolen:=j;
  410. { flags }
  411. skipspace;
  412. while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
  413. begin
  414. hs:=readstr;
  415. if hs='none' then
  416. break;
  417. if x86_64 then
  418. begin
  419. { x86_64 }
  420. if (upcase(hs)='NOX86_64') or (upcase(hs)='16BITONLY') then
  421. skip:=true;
  422. end
  423. else if not i8086 then
  424. begin
  425. { i386 }
  426. if (upcase(hs)='X86_64') or (upcase(hs)='16BITONLY') then
  427. skip:=true;
  428. end
  429. else
  430. begin
  431. { i8086 }
  432. if (upcase(hs)='X86_64') then
  433. skip:=true;
  434. end;
  435. if hs<>'ND' then
  436. begin
  437. { Addition by J. Gareth "Kit" Moreton }
  438. { Workaround for routines that take a 64-bit destination but a 32-bit operand in a non-decorated opcode }
  439. if (lower(hs)='sm') and (SignCheck > 0) then
  440. begin
  441. { Remove signed flag }
  442. StrSearch := Pos(SIGNED_INT, optypes[SignCheck]);
  443. Delete(optypes[SignCheck], StrSearch, Length(SIGNED_INT));
  444. end;
  445. if flags<>'' then
  446. flags:=flags+',';
  447. flags:=flags+'if_'+lower(hs);
  448. end;
  449. if (s[i]=',') and (i<=length(s)) then
  450. inc(i)
  451. else
  452. break;
  453. end;
  454. { write instruction }
  455. if not skip then
  456. begin
  457. if not instrwritten then
  458. DoWriteInstr;
  459. instrwritten:=true;
  460. if not(first) then
  461. writeln(insfile,',')
  462. else
  463. first:=false;
  464. writeln(insfile,' (');
  465. writeln(insfile,' opcode : ',opcode,';');
  466. writeln(insfile,' ops : ',ops,';');
  467. writeln(insfile,' optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
  468. writeln(insfile,' code : ',codes,';');
  469. writeln(insfile,' flags : [',flags,']');
  470. write(insfile,' )');
  471. inc(insns);
  472. end;
  473. end;
  474. close(infile);
  475. closeinc(insfile);
  476. closeinc(intfile);
  477. closeinc(attfile);
  478. closeinc(attsuffile);
  479. closeinc(opfile);
  480. writeln(nopfile,insns,';');
  481. close(nopfile);
  482. closeinc(propfile);
  483. writeln(insns,' nodes processed (maxinfolen=',maxinfolen,')');
  484. end.