mkarminl.pp 17 KB

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