mkx86inl.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. program mkx86inl;
  2. {$mode objfpc}
  3. {$H+}
  4. uses
  5. sysutils, classes,
  6. strutils;
  7. type
  8. TOperDirection = (operIn, operVar, operOut);
  9. TOperand = record
  10. name,
  11. typ: string;
  12. direction: TOperDirection;
  13. end;
  14. const
  15. DirLUT: array[TOperDirection] of string = ('','var ','out ');
  16. function GetPascalType(const ATyp: string): string;
  17. begin
  18. case ATyp of
  19. 'r32': exit('longword');
  20. 'rs32': exit('longint');
  21. 'r64': exit('qword');
  22. 'rs64': exit('int64');
  23. 'f32': exit('single');
  24. 'mm': exit('__m64');
  25. 'xmm': exit('__m128');
  26. 'i32': exit('longint');
  27. 'ptr32': exit('pointer');
  28. else
  29. exit(ATyp);
  30. end;
  31. end;
  32. function GetTypeDef(const ATyp: string): string;
  33. begin
  34. case ATyp of
  35. 'r32': exit('u32inttype');
  36. 'rs32': exit('s32inttype');
  37. 'r64': exit('u64inttype');
  38. 'rs64': exit('s64inttype');
  39. 'f32': exit('s32floattype');
  40. 'mm': exit('x86_m64type');
  41. 'xmm': exit('x86_m128type');
  42. 'i32': exit('s32inttype');
  43. 'ptr32': exit('voidpointertype');
  44. else
  45. exit(ATyp);
  46. end;
  47. end;
  48. function GetOper(const ATyp: string): string;
  49. begin
  50. case ATyp of
  51. 'r32': exit('_reg');
  52. 'rs32': exit('_reg');
  53. 'r64': exit('_reg_reg');
  54. 'rs64': exit('_reg_reg');
  55. 'f32': exit('_reg');
  56. 'mm': exit('_reg');
  57. 'xmm': exit('_reg');
  58. 'i32': exit('_const');
  59. 'ptr32': exit('_ref');
  60. else
  61. exit('');
  62. end;
  63. end;
  64. function GetOperand(const ATyp: string; AIndex: longint): string;
  65. begin
  66. case ATyp of
  67. 'r32': exit(format(',paraarray[%d].location.register', [AIndex]));
  68. 'rs32': exit(format(',paraarray[%d].location.register', [AIndex]));
  69. 'r64': exit(format(',paraarray[%d].location.register64.reglo,paraarray[%d].location.register64.reghi', [AIndex,AIndex]));
  70. 'rs64': exit(format(',paraarray[%d].location.register64.reglo,paraarray[%d].location.register64.reghi', [AIndex,AIndex]));
  71. 'f32': exit(format(',paraarray[%d].location.register', [AIndex]));
  72. 'mm': exit(format(',paraarray[%d].location.register', [AIndex]));
  73. 'xmm': exit(format(',paraarray[%d].location.register', [AIndex]));
  74. 'i32': exit(format(',GetConstInt(paraarray[%d])',[AIndex]));
  75. 'ptr32': exit(format(',paraarray[%d].location.reference', [AIndex]));
  76. else
  77. exit(ATyp);
  78. end;
  79. end;
  80. function GetOperandLoc(const ATyp: string): string;
  81. begin
  82. result:='';
  83. case ATyp of
  84. 'r32': exit(',location.register');
  85. 'rs32': exit(',location.register');
  86. 'r64': exit(',location.register64.reglo,location.register64.reghi');
  87. 'rs64': exit(',location.register64.reglo,location.register64.reghi');
  88. 'f32': exit(',location.register');
  89. 'mm': exit(',location.register');
  90. 'xmm': exit(',location.register');
  91. end;
  92. end;
  93. function GetLocStatement(AIndex: longint; const ATyp: string; AConst: boolean): string;
  94. begin
  95. result:='';
  96. case ATyp of
  97. 'r32': exit(format('hlcg.location_force_reg(current_asmdata.CurrAsmList, paraarray[%d].location, paraarray[%d].resultdef,u32inttype,%s);', [AIndex+1, AIndex+1, BoolToStr(aconst,'true','false')]));
  98. 'rs32': exit(format('hlcg.location_force_reg(current_asmdata.CurrAsmList, paraarray[%d].location, paraarray[%d].resultdef,u32inttype,%s);', [AIndex+1, AIndex+1, BoolToStr(aconst,'true','false')]));
  99. 'r64': exit(format('hlcg.location_force_reg(current_asmdata.CurrAsmList, paraarray[%d].location, paraarray[%d].resultdef,u64inttype,%s);', [AIndex+1, AIndex+1, BoolToStr(aconst,'true','false')]));
  100. 'rs64': exit(format('hlcg.location_force_reg(current_asmdata.CurrAsmList, paraarray[%d].location, paraarray[%d].resultdef,u64inttype,%s);', [AIndex+1, AIndex+1, BoolToStr(aconst,'true','false')]));
  101. 'f32': exit(format('location_force_mmreg(current_asmdata.CurrAsmList, paraarray[%d].location, %s);', [AIndex+1, BoolToStr(aconst,'true','false')]));
  102. 'mm': exit(format('location_force_mmxreg(current_asmdata.CurrAsmList, paraarray[%d].location, %s);', [AIndex+1, BoolToStr(aconst,'true','false')]));
  103. 'xmm': exit(format('location_force_mmreg(current_asmdata.CurrAsmList, paraarray[%d].location, %s);', [AIndex+1, BoolToStr(aconst,'true','false')]));
  104. 'ptr32': exit(format('location_make_ref(paraarray[%d].location);', [AIndex+1]));
  105. end;
  106. end;
  107. function GetLoc(const ATyp: string; AWithSize: boolean = true): string;
  108. begin
  109. result:='';
  110. if AWithSize then
  111. case ATyp of
  112. 'r32': exit('LOC_REGISTER,OS_32');
  113. 'rs32': exit('LOC_REGISTER,OS_S32');
  114. 'r64': exit('LOC_REGISTER,OS_64');
  115. 'rs64': exit('LOC_REGISTER,OS_S64');
  116. 'f32': exit('LOC_MMREGISTER,OS_M128');
  117. 'mm': exit('LOC_MMXREGISTER,OS_M64');
  118. 'xmm': exit('LOC_MMREGISTER,OS_M128');
  119. 'ptr32': exit('LOC_MEM,OS_32');
  120. end
  121. else
  122. case ATyp of
  123. 'r32': exit('LOC_REGISTER');
  124. 'rs32': exit('LOC_REGISTER');
  125. 'r64': exit('LOC_REGISTER');
  126. 'rs64': exit('LOC_REGISTER');
  127. 'f32': exit('LOC_MMREGISTER');
  128. 'mm': exit('LOC_MMXREGISTER');
  129. 'xmm': exit('LOC_MMREGISTER');
  130. 'ptr32': exit('LOC_MEM');
  131. end;
  132. end;
  133. function GetLocAllocation(const ATyp: string): string;
  134. begin
  135. result:='';
  136. case ATyp of
  137. 'r32': exit('location.register:=cg.getintregister(current_asmdata.CurrAsmList, OS_32);');
  138. 'rs32': exit('location.register:=cg.getintregister(current_asmdata.CurrAsmList, OS_32);');
  139. 'r64': exit('location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList, OS_32); location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList, OS_32);');
  140. 'rs64': exit('location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList, OS_32); location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList, OS_32);');
  141. 'f32': exit('location.register:=cg.getmmregister(current_asmdata.CurrAsmList, OS_M128);');
  142. 'mm': exit('location.register:=tcgx86(cg).getmmxregister(current_asmdata.CurrAsmList);');
  143. 'xmm': exit('location.register:=cg.getmmregister(current_asmdata.CurrAsmList, OS_M128);');
  144. end;
  145. end;
  146. function GetPostFix(const APF: string): string;
  147. begin
  148. if APF<>'' then
  149. result:='PF_'+APF
  150. else
  151. result:='PF_None';
  152. end;
  153. procedure ParseList(const APrefix, AFilename: string);
  154. var
  155. f: TextFile;
  156. fprocs,
  157. fcinnr, fcpumminnr: TextFile;
  158. ftypechk, ffirst, fsecond: TStringList;
  159. str,
  160. instrPart,postfix,_alias,
  161. params, operline: String;
  162. opers: array[0..7] of TOperand;
  163. opercnt: longint;
  164. hasOutput: boolean;
  165. outputType: string;
  166. cnt,
  167. i, intrnum: longint;
  168. tmp: String;
  169. function ParseOperands(AIndex: longint = -1): string;
  170. var
  171. idx: LongInt;
  172. pt: Integer;
  173. c: Char;
  174. begin
  175. idx:=opercnt;
  176. params:=trim(params);
  177. if params='' then
  178. exit('');
  179. inc(opercnt);
  180. if pos('var ', params)=1 then
  181. begin
  182. opers[idx].direction:=operVar;
  183. Delete(params,1,4);
  184. params:=trim(params);
  185. hasOutput:=true;
  186. end
  187. else if pos('out ', params)=1 then
  188. begin
  189. opers[idx].direction:=operOut;
  190. Delete(params,1,4);
  191. params:=trim(params);
  192. hasOutput:=true;
  193. end
  194. else
  195. begin
  196. if AIndex<>-1 then
  197. opers[idx].direction:=opers[AIndex].direction
  198. else
  199. opers[idx].direction:=operIn;
  200. end;
  201. pt:=PosSet([',',':'], params);
  202. c:=params[pt];
  203. opers[idx].name:=Copy2SymbDel(params, c);
  204. params:=trim(params);
  205. if c = ':' then
  206. begin
  207. opers[idx].typ:=Copy2SymbDel(params, ';');
  208. result:=opers[idx].typ;
  209. end
  210. else
  211. begin
  212. opers[idx].typ:=ParseOperands(idx);
  213. result:=opers[idx].typ;
  214. end;
  215. if opers[idx].direction<>operIn then
  216. outputType:=opers[idx].typ;
  217. end;
  218. function GetOperLine: string;
  219. var
  220. i: longint;
  221. begin
  222. result:='';
  223. for i := 0 to opercnt-1 do
  224. result:=result+DirLUT[opers[i].direction]+opers[i].name+':'+opers[i].typ+';';
  225. end;
  226. function GetParams: longint;
  227. var
  228. i: longint;
  229. begin
  230. result:=0;
  231. for i := 0 to opercnt-1 do
  232. if opers[i].direction in [operIn,operVar] then
  233. inc(result);
  234. end;
  235. function FindOperIdx(const AOper: string): longint;
  236. var
  237. i,cnt: longint;
  238. begin
  239. cnt:=0;
  240. result:=0;
  241. for i := 0 to opercnt-1 do
  242. if (opers[i].direction in [operIn,operVar]) then
  243. begin
  244. if opers[i].name=AOper then
  245. exit(cnt);
  246. inc(cnt);
  247. end;
  248. end;
  249. begin
  250. intrnum:=0;
  251. assignfile(f, AFilename);
  252. reset(f);
  253. assignfile(fprocs, 'cpummprocs.inc'); rewrite(fprocs);
  254. assignfile(fcinnr, 'c'+APrefix+'mminnr.inc'); rewrite(fcinnr);
  255. assignfile(fcpumminnr, 'cpumminnr.inc'); rewrite(fcpumminnr);
  256. // writeln(finnr,'const');
  257. ftypechk:=TStringList.Create;
  258. ffirst:=TStringList.Create;
  259. fsecond:=TStringList.Create;
  260. // writeln(finnr, ' fpc_in_', APrefix,'_first = fpc_in_',APrefix,'_base;');
  261. while not EOF(f) do
  262. begin
  263. readln(f, str);
  264. str:=trim(str);
  265. if (str='') or (Pos(';',str)=1) then
  266. continue;
  267. instrPart:=Copy2SymbDel(str, '(');
  268. // Check for postfix
  269. if pos('{',instrPart)>0 then
  270. begin
  271. postfix:=instrPart;
  272. instrPart:=Copy2SymbDel(postfix, '{');
  273. postfix:=TrimRightSet(postfix,['}']);
  274. end
  275. else
  276. postfix:='';
  277. // Check for alias
  278. if pos('[',instrPart)>0 then
  279. begin
  280. _alias:=instrPart;
  281. instrPart:=Copy2SymbDel(_alias, '[');
  282. _alias:='_'+TrimRightSet(_alias,[']']);
  283. end
  284. else
  285. _alias:='';
  286. // Get parameters
  287. params:=trim(Copy2SymbDel(str,')'));
  288. str:=trim(str);
  289. hasOutput:=false;
  290. opercnt:=0;
  291. outputType:='';
  292. while params<>'' do
  293. ParseOperands;
  294. operline:=GetOperLine;
  295. // Write typecheck code
  296. i:=ftypechk.IndexOf(': //'+operline);
  297. if i>=0 then
  298. ftypechk.Insert(i,',in_'+APrefix+'_'+instrPart+postfix+_alias)
  299. else
  300. begin
  301. ftypechk.Add('in_'+APrefix+'_'+instrPart+postfix+_alias);
  302. ftypechk.Add(': //'+operline);
  303. ftypechk.Add(' begin');
  304. ftypechk.Add(' CheckParameters('+inttostr(GetParams())+');');
  305. if hasOutput then
  306. ftypechk.Add(' resultdef:='+GetTypeDef(outputType)+';')
  307. else
  308. ftypechk.Add(' resultdef:=voidtype;');
  309. ftypechk.Add(' end;')
  310. end;
  311. // Write firstpass code
  312. i:=ffirst.IndexOf(': //'+operline);
  313. if i>=0 then
  314. ffirst.Insert(i,',in_'+APrefix+'_'+instrPart+postfix+_alias)
  315. else
  316. begin
  317. ffirst.Add('in_'+APrefix+'_'+instrPart+postfix+_alias);
  318. ffirst.Add(': //'+operline);
  319. ffirst.Add(' begin');
  320. if hasOutput then
  321. ffirst.Add(' expectloc:='+GetLoc(outputType,false)+';')
  322. else
  323. ffirst.Add(' expectloc:=LOC_VOID;');
  324. ffirst.Add(' result:=nil;');
  325. ffirst.Add(' end;')
  326. end;
  327. // Write secondpass code
  328. i:=fsecond.IndexOf(': //'+operline);
  329. if i>=0 then
  330. begin
  331. fsecond.Insert(i+3,' in_'+APrefix+'_'+instrPart+postfix+_alias+': begin op:=A_'+instrPart+' end;');
  332. fsecond.Insert(i,',in_'+APrefix+'_'+instrPart+postfix+_alias);
  333. end
  334. else
  335. begin
  336. fsecond.Add('in_'+APrefix+'_'+instrPart+postfix+_alias);
  337. fsecond.Add(': //'+operline);
  338. fsecond.Add(' begin');
  339. fsecond.Add(' case inlinenumber of');
  340. fsecond.Add(' in_'+APrefix+'_'+instrPart+postfix+_alias+': begin op:=A_'+instrPart+'; end;');
  341. fsecond.Add(' else');
  342. fsecond.Add(' Internalerror(2020010201);');
  343. fsecond.Add(' end;');
  344. fsecond.Add('');
  345. i:=GetParams;
  346. fsecond.Add(' GetParameters('+inttostr(i)+');');
  347. fsecond.Add('');
  348. fsecond.Add(' for i := 1 to '+inttostr(i)+' do secondpass(paraarray[i]);');
  349. fsecond.Add('');
  350. // Force inputs
  351. cnt:=0;
  352. for i := 0 to opercnt-1 do
  353. begin
  354. case opers[i].direction of
  355. operIn:
  356. begin
  357. tmp:=GetLocStatement(cnt, opers[i].typ, true);
  358. if tmp<>'' then
  359. fsecond.add(' '+tmp);
  360. inc(cnt);
  361. end;
  362. operVar:
  363. begin
  364. tmp:=GetLocStatement(cnt, opers[i].typ, false);
  365. if tmp<>'' then
  366. fsecond.add(' '+tmp);
  367. inc(cnt);
  368. end;
  369. end;
  370. end;
  371. // Allocate output
  372. cnt:=0;
  373. for i := 0 to opercnt-1 do
  374. begin
  375. case opers[i].direction of
  376. operOut:
  377. begin
  378. fsecond.add(' location_reset(location,'+GetLoc(opers[i].typ)+');');
  379. fsecond.Add(' '+GetLocAllocation(opers[i].typ));
  380. end;
  381. operVar:
  382. begin
  383. fsecond.Add(' location:=paraarray['+inttostr(cnt+1)+'].location;');
  384. inc(cnt);
  385. end;
  386. operIn:
  387. inc(cnt);
  388. end;
  389. end;
  390. operline:='taicpu.op';
  391. //for i := 0 to opercnt-1 do
  392. for i := opercnt-1 downto 0 do
  393. begin
  394. case opers[i].direction of
  395. operOut:
  396. operline:=operline+GetOper(opers[i].typ);
  397. operVar:
  398. operline:=operline+GetOper(opers[i].typ);
  399. operIn:
  400. operline:=operline+GetOper(opers[i].typ);
  401. end;
  402. end;
  403. if operline='taicpu.op' then
  404. operline:='taicpu.op_none(op,S_NO'
  405. else
  406. operline:=operline+'(op,S_NO';
  407. //for i := 0 to opercnt-1 do
  408. for i := opercnt-1 downto 0 do
  409. begin
  410. case opers[i].direction of
  411. operOut:
  412. operline:=operline+GetOperandLoc(opers[i].typ);
  413. operIn,
  414. operVar:
  415. begin
  416. dec(cnt);
  417. operline:=operline+GetOperand(opers[i].typ, cnt+1);
  418. end;
  419. end;
  420. end;
  421. operline:=operline+')';
  422. fsecond.Add(' current_asmdata.CurrAsmList.concat('+operline+');');
  423. fsecond.Add(' end;')
  424. end;
  425. // Write innr
  426. writeln(fcinnr, ' in_', APrefix,'_',instrPart,postfix+_alias,' = in_',APrefix,'_mm_first+',intrnum,',');
  427. writeln(fcpumminnr, ' fpc_in_', APrefix,'_',instrPart,postfix+_alias,' = fpc_in_',APrefix,'_mm_first+',intrnum,';');
  428. // Write function
  429. if hasOutput then write(fprocs,'function ') else write(fprocs,'procedure ');
  430. write(fprocs,APrefix,'_',instrPart,postfix,'(');
  431. cnt:=0;
  432. for i:=0 to opercnt-1 do
  433. begin
  434. if opers[i].direction=operOut then
  435. Continue;
  436. if cnt>0 then
  437. begin
  438. if opers[i].typ<>opers[i-1].typ then
  439. write(fprocs,': ',GetPascalType(opers[i-1].typ),'; ')
  440. else
  441. write(fprocs,', ');
  442. end;
  443. write(fprocs,opers[i].name);
  444. if i=opercnt-1 then
  445. write(fprocs,': ',GetPascalType(opers[i].typ));
  446. inc(cnt);
  447. end;
  448. write(fprocs,')');
  449. if hasOutput then write(fprocs,': ',GetPascalType(outputType));
  450. writeln(fprocs,'; [INTERNPROC: fpc_in_',APrefix,'_',instrPart,postfix+_alias,'];');
  451. // Str now contains conditionals
  452. inc(intrnum);
  453. end;
  454. writeln(fcinnr, ' in_', APrefix,'mm_last = in_',APrefix,'_mm_first+',intrnum-1);
  455. ftypechk.SaveToFile(APrefix+'mmtype.inc');
  456. ffirst.SaveToFile(APrefix+'mmfirst.inc');
  457. fsecond.SaveToFile(APrefix+'mmsecond.inc');
  458. ftypechk.Free;
  459. ffirst.Free;
  460. fsecond.Free;
  461. CloseFile(fprocs);
  462. CloseFile(fcinnr);
  463. CloseFile(fcpumminnr);
  464. closefile(f);
  465. end;
  466. begin
  467. ParseList('x86', 'x86intr.dat');
  468. end.