mkx86ins.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. 'S' :
  299. begin
  300. dec(attopcode[0]);
  301. attsuffix:='attsufMMS';
  302. end;
  303. 'X' :
  304. begin
  305. dec(attopcode[0]);
  306. attsuffix:='attsufINT';
  307. end;
  308. 'Y' :
  309. begin
  310. dec(attopcode[0]);
  311. attsuffix:='attsufINTdual';
  312. end;
  313. 'F' :
  314. begin
  315. dec(attopcode[0]);
  316. attsuffix:='attsufFPU';
  317. end;
  318. 'R' :
  319. begin
  320. dec(attopcode[0]);
  321. attsuffix:='attsufFPUint';
  322. end;
  323. else
  324. attsuffix:='attsufNONE';
  325. end;
  326. { att Conditional }
  327. if (attopcode[length(attopcode)]='C') and
  328. (attopcode[length(attopcode)-1]='C') then
  329. dec(byte(attopcode[0]),2);
  330. end;
  331. intopcode:=Lower(intopcode);
  332. attopcode:=Lower(attopcode);
  333. instrwritten:=false;
  334. { read the next line which contains the Change options }
  335. repeat
  336. readln(infile,inschanges);
  337. until eof(infile) or ((inschanges<>'') and (inschanges[1]<>';'));
  338. inschanges[1]:='[';
  339. inschanges[length(inschanges)]:=']';
  340. continue;
  341. end;
  342. { we must have an opcode }
  343. if opcode='' then
  344. runerror(234);
  345. { clear }
  346. ops:=0;
  347. for i:=low(optypes) to high(optypes) do
  348. optypes[i]:='';
  349. codes:='';
  350. flags:='';
  351. skip:=false;
  352. { ops and optypes }
  353. i:=1;
  354. repeat
  355. hs:=readstr;
  356. if (hs='void') or (hs='ignore') then
  357. break;
  358. inc(ops);
  359. optypes[ops]:=optypes[ops]+'ot_'+formatop(hs,false);
  360. while s[i]='|' do
  361. begin
  362. inc(i);
  363. optypes[ops]:=optypes[ops]+' or ot_'+formatop(readstr,true);
  364. end;
  365. if s[i] in [',',':'] then
  366. inc(i)
  367. else
  368. break;
  369. until false;
  370. for j:=1 to max_operands-ops do
  371. optypes[max_operands-j+1]:='ot_none';
  372. { codes }
  373. skipspace;
  374. j:=0;
  375. literalcount:=0;
  376. if s[i] in ['\','0'..'9'] then
  377. begin
  378. while not(s[i] in [' ',#9]) do
  379. begin
  380. code:=readnumber;
  381. { for some codes we want also to change the optypes, but not
  382. if the code belongs to a literal sequence }
  383. if (literalcount=0) and (code>=1) and (code<=3) then
  384. literalcount:=code
  385. else
  386. begin
  387. if literalcount>0 then
  388. dec(literalcount)
  389. else
  390. begin
  391. case code of
  392. 12,13,14: {signed byte}
  393. optypes[code-11]:=optypes[code-11]+SIGNED_INT;
  394. 172,173,174: {signed long}
  395. begin
  396. { Addition by J. Gareth "Kit" Moreton }
  397. { See below for workaround for routines that take a 64-bit destination but a 32-bit operand in a non-decorated opcode }
  398. SignCheck := code-171;
  399. optypes[SignCheck]:=optypes[SignCheck]+SIGNED_INT;
  400. end;
  401. end;
  402. end;
  403. end;
  404. codes:=codes+'#'+tostr(code);
  405. inc(j);
  406. end;
  407. end
  408. else
  409. begin
  410. readstr;
  411. codes:='#0';
  412. end;
  413. if j>maxinfolen then
  414. maxinfolen:=j;
  415. { flags }
  416. skipspace;
  417. while not(s[i] in [' ',#9,#13,#10]) and (i<=length(s)) do
  418. begin
  419. hs:=readstr;
  420. if hs='none' then
  421. break;
  422. if x86_64 then
  423. begin
  424. { x86_64 }
  425. if (upcase(hs)='NOX86_64') or (upcase(hs)='16BITONLY') then
  426. skip:=true;
  427. end
  428. else if not i8086 then
  429. begin
  430. { i386 }
  431. if (upcase(hs)='X86_64') or (upcase(hs)='16BITONLY') then
  432. skip:=true;
  433. end
  434. else
  435. begin
  436. { i8086 }
  437. if (upcase(hs)='X86_64') then
  438. skip:=true;
  439. end;
  440. if hs<>'ND' then
  441. begin
  442. { Addition by J. Gareth "Kit" Moreton }
  443. { Workaround for routines that take a 64-bit destination but a 32-bit operand in a non-decorated opcode }
  444. if (lower(hs)='sm') and (SignCheck > 0) then
  445. begin
  446. { Remove signed flag }
  447. StrSearch := Pos(SIGNED_INT, optypes[SignCheck]);
  448. Delete(optypes[SignCheck], StrSearch, Length(SIGNED_INT));
  449. end;
  450. if flags<>'' then
  451. flags:=flags+',';
  452. flags:=flags+'if_'+lower(hs);
  453. end;
  454. if (s[i]=',') and (i<=length(s)) then
  455. inc(i)
  456. else
  457. break;
  458. end;
  459. { write instruction }
  460. if not skip then
  461. begin
  462. if not instrwritten then
  463. DoWriteInstr;
  464. instrwritten:=true;
  465. if not(first) then
  466. writeln(insfile,',')
  467. else
  468. first:=false;
  469. writeln(insfile,' (');
  470. writeln(insfile,' opcode : ',opcode,';');
  471. writeln(insfile,' ops : ',ops,';');
  472. writeln(insfile,' optypes : (',optypes[1],',',optypes[2],',',optypes[3],',',optypes[4],');');
  473. writeln(insfile,' code : ',codes,';');
  474. writeln(insfile,' flags : [',flags,']');
  475. write(insfile,' )');
  476. inc(insns);
  477. end;
  478. end;
  479. close(infile);
  480. closeinc(insfile);
  481. closeinc(intfile);
  482. closeinc(attfile);
  483. closeinc(attsuffile);
  484. closeinc(opfile);
  485. writeln(nopfile,insns,';');
  486. close(nopfile);
  487. closeinc(propfile);
  488. writeln(insns,' nodes processed (maxinfolen=',maxinfolen,')');
  489. end.