mkarminl.pp 17 KB

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