2
0

mkx86inl.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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. finnr: 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, APrefix+'procs.inc'); rewrite(fprocs);
  254. assignfile(finnr, APrefix+'innr.inc'); rewrite(finnr);
  255. writeln(finnr,'const');
  256. ftypechk:=TStringList.Create;
  257. ffirst:=TStringList.Create;
  258. fsecond:=TStringList.Create;
  259. writeln(finnr, ' in_', APrefix,'_first = in_',APrefix,'_base;');
  260. while not EOF(f) do
  261. begin
  262. readln(f, str);
  263. str:=trim(str);
  264. if (str='') or (Pos(';',str)=1) then
  265. continue;
  266. instrPart:=Copy2SymbDel(str, '(');
  267. // Check for postfix
  268. if pos('{',instrPart)>0 then
  269. begin
  270. postfix:=instrPart;
  271. instrPart:=Copy2SymbDel(postfix, '{');
  272. postfix:=TrimRightSet(postfix,['}']);
  273. end
  274. else
  275. postfix:='';
  276. // Check for alias
  277. if pos('[',instrPart)>0 then
  278. begin
  279. _alias:=instrPart;
  280. instrPart:=Copy2SymbDel(_alias, '[');
  281. _alias:='_'+TrimRightSet(_alias,[']']);
  282. end
  283. else
  284. _alias:='';
  285. // Get parameters
  286. params:=trim(Copy2SymbDel(str,')'));
  287. str:=trim(str);
  288. hasOutput:=false;
  289. opercnt:=0;
  290. outputType:='';
  291. while params<>'' do
  292. ParseOperands;
  293. operline:=GetOperLine;
  294. // Write typecheck code
  295. i:=ftypechk.IndexOf(': //'+operline);
  296. if i>=0 then
  297. ftypechk.Insert(i,',in_'+APrefix+'_'+instrPart+postfix+_alias)
  298. else
  299. begin
  300. ftypechk.Add('in_'+APrefix+'_'+instrPart+postfix+_alias);
  301. ftypechk.Add(': //'+operline);
  302. ftypechk.Add(' begin');
  303. ftypechk.Add(' CheckParameters('+inttostr(GetParams())+');');
  304. if hasOutput then
  305. ftypechk.Add(' resultdef:='+GetTypeDef(outputType)+';')
  306. else
  307. ftypechk.Add(' resultdef:=voidtype;');
  308. ftypechk.Add(' end;')
  309. end;
  310. // Write firstpass code
  311. i:=ffirst.IndexOf(': //'+operline);
  312. if i>=0 then
  313. ffirst.Insert(i,',in_'+APrefix+'_'+instrPart+postfix+_alias)
  314. else
  315. begin
  316. ffirst.Add('in_'+APrefix+'_'+instrPart+postfix+_alias);
  317. ffirst.Add(': //'+operline);
  318. ffirst.Add(' begin');
  319. if hasOutput then
  320. ffirst.Add(' expectloc:='+GetLoc(outputType,false)+';')
  321. else
  322. ffirst.Add(' expectloc:=LOC_VOID;');
  323. ffirst.Add(' result:=nil;');
  324. ffirst.Add(' end;')
  325. end;
  326. // Write secondpass code
  327. i:=fsecond.IndexOf(': //'+operline);
  328. if i>=0 then
  329. begin
  330. fsecond.Insert(i+3,' in_'+APrefix+'_'+instrPart+postfix+_alias+': begin op:=A_'+instrPart+' end;');
  331. fsecond.Insert(i,',in_'+APrefix+'_'+instrPart+postfix+_alias);
  332. end
  333. else
  334. begin
  335. fsecond.Add('in_'+APrefix+'_'+instrPart+postfix+_alias);
  336. fsecond.Add(': //'+operline);
  337. fsecond.Add(' begin');
  338. fsecond.add(' case inlinenumber of');
  339. fsecond.Add(' in_'+APrefix+'_'+instrPart+postfix+_alias+': begin op:=A_'+instrPart+'; end;');
  340. fsecond.add(' end;');
  341. fsecond.Add('');
  342. i:=GetParams;
  343. fsecond.Add(' GetParameters('+inttostr(i)+');');
  344. fsecond.Add('');
  345. fsecond.add(' for i := 1 to '+inttostr(i)+' do secondpass(paraarray[i]);');
  346. fsecond.Add('');
  347. // Force inputs
  348. cnt:=0;
  349. for i := 0 to opercnt-1 do
  350. begin
  351. case opers[i].direction of
  352. operIn:
  353. begin
  354. tmp:=GetLocStatement(cnt, opers[i].typ, true);
  355. if tmp<>'' then
  356. fsecond.add(' '+tmp);
  357. inc(cnt);
  358. end;
  359. operVar:
  360. begin
  361. tmp:=GetLocStatement(cnt, opers[i].typ, false);
  362. if tmp<>'' then
  363. fsecond.add(' '+tmp);
  364. inc(cnt);
  365. end;
  366. end;
  367. end;
  368. // Allocate output
  369. cnt:=0;
  370. for i := 0 to opercnt-1 do
  371. begin
  372. case opers[i].direction of
  373. operOut:
  374. begin
  375. fsecond.add(' location_reset(location,'+GetLoc(opers[i].typ)+');');
  376. fsecond.Add(' '+GetLocAllocation(opers[i].typ));
  377. end;
  378. operVar:
  379. begin
  380. fsecond.Add(' location:=paraarray['+inttostr(cnt+1)+'].location;');
  381. inc(cnt);
  382. end;
  383. operIn:
  384. inc(cnt);
  385. end;
  386. end;
  387. operline:='taicpu.op';
  388. //for i := 0 to opercnt-1 do
  389. for i := opercnt-1 downto 0 do
  390. begin
  391. case opers[i].direction of
  392. operOut:
  393. operline:=operline+GetOper(opers[i].typ);
  394. operVar:
  395. operline:=operline+GetOper(opers[i].typ);
  396. operIn:
  397. operline:=operline+GetOper(opers[i].typ);
  398. end;
  399. end;
  400. if operline='taicpu.op' then
  401. operline:='taicpu.op_none(op,S_NO'
  402. else
  403. operline:=operline+'(op,S_NO';
  404. //for i := 0 to opercnt-1 do
  405. for i := opercnt-1 downto 0 do
  406. begin
  407. case opers[i].direction of
  408. operOut:
  409. operline:=operline+GetOperandLoc(opers[i].typ);
  410. operIn,
  411. operVar:
  412. begin
  413. dec(cnt);
  414. operline:=operline+GetOperand(opers[i].typ, cnt+1);
  415. end;
  416. end;
  417. end;
  418. operline:=operline+')';
  419. fsecond.Add(' current_asmdata.CurrAsmList.concat('+operline+');');
  420. fsecond.Add(' end;')
  421. end;
  422. // Write innr
  423. writeln(finnr, ' in_', APrefix,'_',instrPart,postfix+_alias,' = in_',APrefix,'_base+',intrnum,';');
  424. // Write function
  425. if hasOutput then write(fprocs,'function ') else write(fprocs,'procedure ');
  426. write(fprocs,APrefix,'_',instrPart,postfix,'(');
  427. cnt:=0;
  428. for i:=0 to opercnt-1 do
  429. begin
  430. if opers[i].direction=operOut then
  431. Continue;
  432. if cnt>0 then
  433. begin
  434. if opers[i].typ<>opers[i-1].typ then
  435. write(fprocs,': ',GetPascalType(opers[i-1].typ),'; ')
  436. else
  437. write(fprocs,', ');
  438. end;
  439. write(fprocs,opers[i].name);
  440. if i=opercnt-1 then
  441. write(fprocs,': ',GetPascalType(opers[i].typ));
  442. inc(cnt);
  443. end;
  444. write(fprocs,')');
  445. if hasOutput then write(fprocs,': ',GetPascalType(outputType));
  446. writeln(fprocs,'; [INTERNPROC: in_',APrefix,'_',instrPart,postfix+_alias,'];');
  447. // Str now contains conditionals
  448. inc(intrnum);
  449. end;
  450. writeln(finnr, ' in_', APrefix,'_last = in_',APrefix,'_base+',intrnum-1,';');
  451. ftypechk.SaveToFile(APrefix+'type.inc');
  452. ffirst.SaveToFile(APrefix+'first.inc');
  453. fsecond.SaveToFile(APrefix+'second.inc');
  454. ftypechk.Free;
  455. ffirst.Free;
  456. fsecond.Free;
  457. CloseFile(fprocs);
  458. CloseFile(finnr);
  459. closefile(f);
  460. end;
  461. begin
  462. ParseList('x86', 'x86intr.dat');
  463. end.