agppcmpw.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. {
  2. Copyright (c) 2002 by Florian Klaempfl
  3. This unit implements an asmoutput class for PowerPC with MPW syntax
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {
  18. This unit implements an asmoutput class for PowerPC with MPW syntax
  19. }
  20. unit agppcmpw;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. aasmtai,aasmdata,
  25. globals,aasmbase,aasmcpu,assemble,
  26. cpubase;
  27. type
  28. TPPCMPWAssembler = class(TExternalAssembler)
  29. procedure WriteTree(p:TAsmList);override;
  30. procedure WriteAsmList;override;
  31. Function DoAssemble:boolean;override;
  32. procedure WriteExternals;
  33. procedure WriteAsmFileHeader;
  34. private
  35. procedure WriteInstruction(hp : tai);
  36. procedure WriteProcedureHeader(var hp:tai);
  37. procedure WriteDataHeader(var s:string; isExported, isConst:boolean);
  38. cur_CSECT_name: String;
  39. cur_CSECT_class: String;
  40. end;
  41. implementation
  42. uses
  43. cutils,globtype,systems,cclasses,
  44. verbose,finput,fmodule,script,cpuinfo,
  45. cgbase,cgutils,
  46. itcpugas
  47. ;
  48. const
  49. line_length = 70;
  50. {Whether internal procedure references should be xxx[PR]: }
  51. use_PR = false;
  52. const_storage_class = '';
  53. var_storage_class = '';
  54. secnames : array[TAsmSectiontype] of string[10] = (
  55. '', {none}
  56. 'csect', {code}
  57. 'csect', {data}
  58. 'csect', {read only data}
  59. 'csect', {bss} 'csect', '',
  60. 'csect','csect','csect','csect',
  61. '','','','','','','','','','','','',''
  62. );
  63. type
  64. t64bitarray = array[0..7] of byte;
  65. t32bitarray = array[0..3] of byte;
  66. function ReplaceForbiddenChars(var s: string):Boolean;
  67. {Returns wheater a replacement has occured.}
  68. var
  69. i:Integer;
  70. {The dollar sign is not allowed in MPW PPCAsm}
  71. begin
  72. ReplaceForbiddenChars:=false;
  73. for i:=1 to Length(s) do
  74. if s[i]='$' then
  75. begin
  76. s[i]:='s';
  77. ReplaceForbiddenChars:=true;
  78. end;
  79. end;
  80. {*** From here is copyed from agppcgas.pp, except where marked with CHANGED.
  81. Perhaps put in a third common file. ***}
  82. function getreferencestring(var ref : treference) : string;
  83. var
  84. s : string;
  85. begin
  86. with ref do
  87. begin
  88. if (refaddr <> addr_no) then
  89. InternalError(2002110301)
  90. else if ((offset < -32768) or (offset > 32767)) then
  91. InternalError(19991);
  92. if assigned(symbol) then
  93. begin
  94. s:= symbol.name;
  95. ReplaceForbiddenChars(s);
  96. {if symbol.typ = AT_FUNCTION then
  97. ;}
  98. s:= s+'[TC]' {ref to TOC entry }
  99. end
  100. else
  101. s:= '';
  102. if offset<0 then
  103. s:=s+tostr(offset)
  104. else
  105. if (offset>0) then
  106. begin
  107. if assigned(symbol) then
  108. s:=s+'+'+tostr(offset)
  109. else
  110. s:=s+tostr(offset);
  111. end;
  112. if (index=NR_NO) and (base<>NR_NO) then
  113. begin
  114. if offset=0 then
  115. if not assigned(symbol) then
  116. s:=s+'0';
  117. s:=s+'('+gas_regname(base)+')';
  118. end
  119. else if (index<>NR_NO) and (base<>NR_NO) and (offset=0) then
  120. begin
  121. if (offset=0) then
  122. s:=s+gas_regname(base)+','+gas_regname(index)
  123. else
  124. internalerror(19992);
  125. end
  126. else if (base=NR_NO) and (offset=0) then
  127. begin
  128. {Temporary fix for inline asm, where a local var is referenced.}
  129. //if assigned(symbol) then
  130. // s:= s+'(rtoc)';
  131. end;
  132. end;
  133. getreferencestring:=s;
  134. end;
  135. function getopstr_jmp(const o:toper) : string;
  136. var
  137. hs : string;
  138. begin
  139. case o.typ of
  140. top_reg :
  141. getopstr_jmp:=gas_regname(o.reg);
  142. { no top_ref jumping for powerpc }
  143. top_const :
  144. getopstr_jmp:=tostr(o.val);
  145. top_ref :
  146. begin
  147. if o.ref^.refaddr=addr_full then
  148. begin
  149. hs:=o.ref^.symbol.name;
  150. ReplaceForbiddenChars(hs);
  151. case o.ref^.symbol.typ of
  152. AT_FUNCTION:
  153. begin
  154. if hs[1] <> '@' then {if not local label}
  155. if use_PR then
  156. hs:= '.'+hs+'[PR]'
  157. else
  158. hs:= '.'+hs
  159. end
  160. else
  161. ;
  162. end;
  163. if o.ref^.offset>0 then
  164. hs:=hs+'+'+tostr(o.ref^.offset)
  165. else
  166. if o.ref^.offset<0 then
  167. hs:=hs+tostr(o.ref^.offset);
  168. getopstr_jmp:=hs;
  169. end
  170. else
  171. internalerror(200402263);
  172. end;
  173. top_none:
  174. getopstr_jmp:='';
  175. else
  176. internalerror(2002070603);
  177. end;
  178. end;
  179. function getopstr(const o:toper) : string;
  180. var
  181. hs : string;
  182. begin
  183. case o.typ of
  184. top_reg:
  185. getopstr:=gas_regname(o.reg);
  186. top_const:
  187. getopstr:=tostr(longint(o.val));
  188. top_ref:
  189. if o.ref^.refaddr=addr_no then
  190. getopstr:=getreferencestring(o.ref^)
  191. else
  192. begin
  193. hs:=o.ref^.symbol.name;
  194. ReplaceForbiddenChars(hs);
  195. if o.ref^.offset>0 then
  196. hs:=hs+'+'+tostr(o.ref^.offset)
  197. else
  198. if o.ref^.offset<0 then
  199. hs:=hs+tostr(o.ref^.offset);
  200. getopstr:=hs;
  201. end;
  202. else
  203. internalerror(2002070604);
  204. end;
  205. end;
  206. function branchmode(o: tasmop): string[4];
  207. var tempstr: string[4];
  208. begin
  209. tempstr := '';
  210. case o of
  211. A_BCCTR,A_BCCTRL: tempstr := 'ctr';
  212. A_BCLR,A_BCLRL: tempstr := 'lr';
  213. end;
  214. case o of
  215. A_BL,A_BLA,A_BCL,A_BCLA,A_BCCTRL,A_BCLRL: tempstr := tempstr+'l';
  216. end;
  217. case o of
  218. A_BA,A_BLA,A_BCA,A_BCLA: tempstr:=tempstr+'a';
  219. end;
  220. branchmode := tempstr;
  221. end;
  222. function cond2str(op: tasmop; c: tasmcond): string;
  223. { note: no checking is performed whether the given combination of }
  224. { conditions is valid }
  225. var
  226. tempstr: string;
  227. begin
  228. tempstr:=#9;
  229. case c.simple of
  230. false:
  231. begin
  232. cond2str := tempstr+gas_op2str[op];
  233. case c.dirhint of
  234. DH_None:;
  235. DH_Minus:
  236. cond2str:=cond2str+'-';
  237. DH_Plus:
  238. cond2str:=cond2str+'+';
  239. else
  240. internalerror(2003112901);
  241. end;
  242. cond2str:=cond2str+#9+tostr(c.bo)+','+tostr(c.bi)+',';
  243. end;
  244. true:
  245. if (op >= A_B) and (op <= A_BCLRL) then
  246. case c.cond of
  247. { unconditional branch }
  248. C_NONE:
  249. cond2str := tempstr+gas_op2str[op];
  250. { bdnzt etc }
  251. else
  252. begin
  253. tempstr := tempstr+'b'+asmcondflag2str[c.cond]+
  254. branchmode(op);
  255. case c.dirhint of
  256. DH_None:
  257. tempstr:=tempstr+#9;
  258. DH_Minus:
  259. tempstr:=tempstr+('-'+#9);
  260. DH_Plus:
  261. tempstr:=tempstr+('+'+#9);
  262. else
  263. internalerror(2003112901);
  264. end;
  265. case c.cond of
  266. C_LT..C_NU:
  267. cond2str := tempstr+gas_regname(newreg(R_SPECIALREGISTER,c.cr,R_SUBWHOLE));
  268. C_T,C_F,C_DNZT,C_DNZF,C_DZT,C_DZF:
  269. cond2str := tempstr+tostr(c.crbit);
  270. else
  271. cond2str := tempstr;
  272. end;
  273. end;
  274. end
  275. { we have a trap instruction }
  276. else
  277. begin
  278. internalerror(2002070601);
  279. { not yet implemented !!!!!!!!!!!!!!!!!!!!! }
  280. { case tempstr := 'tw';}
  281. end;
  282. end;
  283. end;
  284. procedure TPPCMPWAssembler.WriteInstruction(hp : tai);
  285. var op: TAsmOp;
  286. s: string;
  287. i: byte;
  288. sep: string[3];
  289. begin
  290. op:=taicpu(hp).opcode;
  291. if is_calljmp(op) then
  292. begin
  293. { direct BO/BI in op[0] and op[1] not supported, put them in condition! }
  294. case op of
  295. A_B,A_BA:
  296. s:=#9+gas_op2str[op]+#9;
  297. A_BCTR,A_BCTRL,A_BLR,A_BLRL:
  298. s:=#9+gas_op2str[op];
  299. A_BL,A_BLA:
  300. s:=#9+gas_op2str[op]+#9;
  301. else
  302. begin
  303. s:=cond2str(op,taicpu(hp).condition);
  304. if (s[length(s)] <> #9) and
  305. (taicpu(hp).ops>0) then
  306. s := s + ',';
  307. end;
  308. end;
  309. if (taicpu(hp).ops>0) and (taicpu(hp).oper[0]^.typ<>top_none) then
  310. begin
  311. { first write the current contents of s, because the symbol }
  312. { may be 255 characters }
  313. asmwrite(s);
  314. s:=getopstr_jmp(taicpu(hp).oper[0]^);
  315. end;
  316. end
  317. else
  318. { process operands }
  319. begin
  320. s:=#9+gas_op2str[op];
  321. if taicpu(hp).ops<>0 then
  322. begin
  323. sep:=#9;
  324. for i:=0 to taicpu(hp).ops-1 do
  325. begin
  326. s:=s+sep+getopstr(taicpu(hp).oper[i]^);
  327. sep:=',';
  328. end;
  329. end;
  330. end;
  331. AsmWriteLn(s);
  332. end;
  333. {*** Until here is copyed from agppcgas.pp. ***}
  334. function single2str(d : single) : string;
  335. var
  336. hs : string;
  337. p : byte;
  338. begin
  339. str(d,hs);
  340. { nasm expects a lowercase e }
  341. p:=pos('E',hs);
  342. if p>0 then
  343. hs[p]:='e';
  344. p:=pos('+',hs);
  345. if p>0 then
  346. delete(hs,p,1);
  347. single2str:=lower(hs);
  348. end;
  349. function double2str(d : double) : string;
  350. var
  351. hs : string;
  352. p : byte;
  353. begin
  354. str(d,hs);
  355. { nasm expects a lowercase e }
  356. p:=pos('E',hs);
  357. if p>0 then
  358. hs[p]:='e';
  359. p:=pos('+',hs);
  360. if p>0 then
  361. delete(hs,p,1);
  362. double2str:=lower(hs);
  363. end;
  364. { convert floating point values }
  365. { to correct endian }
  366. procedure swap64bitarray(var t: t64bitarray);
  367. var
  368. b: byte;
  369. begin
  370. b:= t[7];
  371. t[7] := t[0];
  372. t[0] := b;
  373. b := t[6];
  374. t[6] := t[1];
  375. t[1] := b;
  376. b:= t[5];
  377. t[5] := t[2];
  378. t[2] := b;
  379. b:= t[4];
  380. t[4] := t[3];
  381. t[3] := b;
  382. end;
  383. procedure swap32bitarray(var t: t32bitarray);
  384. var
  385. b: byte;
  386. begin
  387. b:= t[1];
  388. t[1]:= t[2];
  389. t[2]:= b;
  390. b:= t[0];
  391. t[0]:= t[3];
  392. t[3]:= b;
  393. end;
  394. function fixline(s:string):string;
  395. {
  396. return s with all leading and ending spaces and tabs removed
  397. }
  398. var
  399. i,j,k : longint;
  400. begin
  401. i:=length(s);
  402. while (i>0) and (s[i] in [#9,' ']) do
  403. dec(i);
  404. j:=1;
  405. while (j<i) and (s[j] in [#9,' ']) do
  406. inc(j);
  407. for k:=j to i do
  408. if s[k] in [#0..#31,#127..#255] then
  409. s[k]:='.';
  410. fixline:=Copy(s,j,i-j+1);
  411. end;
  412. Function PadTabs(const p:string;addch:char):string;
  413. var
  414. s : string;
  415. i : longint;
  416. begin
  417. i:=length(p);
  418. if addch<>#0 then
  419. begin
  420. inc(i);
  421. s:=p+addch;
  422. end
  423. else
  424. s:=p;
  425. if i<8 then
  426. PadTabs:=s+#9#9
  427. else
  428. PadTabs:=s+#9;
  429. end;
  430. {****************************************************************************
  431. PowerPC MPW Assembler
  432. ****************************************************************************}
  433. procedure TPPCMPWAssembler.WriteProcedureHeader(var hp:tai);
  434. {Returns the current hp where the caller should continue from}
  435. {For multiple entry procedures, only the last is exported as xxx[PR]
  436. (if use_PR is set) }
  437. procedure WriteExportHeader(hp:tai);
  438. var
  439. s: string;
  440. replaced: boolean;
  441. begin
  442. s:= tai_symbol(hp).sym.name;
  443. replaced:= ReplaceForbiddenChars(s);
  444. if not use_PR then
  445. begin
  446. AsmWrite(#9'export'#9'.');
  447. AsmWrite(s);
  448. if replaced then
  449. begin
  450. AsmWrite(' => ''.');
  451. AsmWrite(tai_symbol(hp).sym.name);
  452. AsmWrite('''');
  453. end;
  454. AsmLn;
  455. end;
  456. AsmWrite(#9'export'#9);
  457. AsmWrite(s);
  458. AsmWrite('[DS]');
  459. if replaced then
  460. begin
  461. AsmWrite(' => ''');
  462. AsmWrite(tai_symbol(hp).sym.name);
  463. AsmWrite('[DS]''');
  464. end;
  465. AsmLn;
  466. {Entry in transition vector: }
  467. AsmWrite(#9'csect'#9); AsmWrite(s); AsmWriteLn('[DS]');
  468. AsmWrite(#9'dc.l'#9'.'); AsmWriteLn(s);
  469. AsmWriteln(#9'dc.l'#9'TOC[tc0]');
  470. {Entry in TOC: }
  471. AsmWriteLn(#9'toc');
  472. AsmWrite(#9'tc'#9);
  473. AsmWrite(s); AsmWrite('[TC],');
  474. AsmWrite(s); AsmWriteln('[DS]');
  475. end;
  476. function GetAdjacentTaiSymbol(var hp:tai):Boolean;
  477. begin
  478. GetAdjacentTaiSymbol:= false;
  479. while assigned(hp.next) do
  480. case tai(hp.next).typ of
  481. ait_symbol:
  482. begin
  483. hp:=tai(hp.next);
  484. GetAdjacentTaiSymbol:= true;
  485. Break;
  486. end;
  487. ait_function_name:
  488. hp:=tai(hp.next);
  489. else
  490. begin
  491. //AsmWriteln(' ;#*#*# ' + tostr(Ord(tai(hp.next).typ)));
  492. Break;
  493. end;
  494. end;
  495. end;
  496. var
  497. first,last: tai;
  498. s: string;
  499. replaced: boolean;
  500. begin
  501. s:= tai_symbol(hp).sym.name;
  502. {Write all headers}
  503. first:= hp;
  504. repeat
  505. WriteExportHeader(hp);
  506. last:= hp;
  507. until not GetAdjacentTaiSymbol(hp);
  508. {Start the section of the body of the proc: }
  509. s:= tai_symbol(last).sym.name;
  510. replaced:= ReplaceForbiddenChars(s);
  511. if use_PR then
  512. begin
  513. AsmWrite(#9'export'#9'.'); AsmWrite(s); AsmWrite('[PR]');
  514. if replaced then
  515. begin
  516. AsmWrite(' => ''.');
  517. AsmWrite(tai_symbol(last).sym.name);
  518. AsmWrite('[PR]''');
  519. end;
  520. AsmLn;
  521. end;
  522. {Starts the section: }
  523. AsmWrite(#9'csect'#9'.');
  524. AsmWrite(s);
  525. AsmWriteLn('[PR]');
  526. {Info for the debugger: }
  527. AsmWrite(#9'function'#9'.');
  528. AsmWrite(s);
  529. AsmWriteLn('[PR]');
  530. {Write all labels: }
  531. hp:= first;
  532. repeat
  533. s:= tai_symbol(hp).sym.name;
  534. ReplaceForbiddenChars(s);
  535. AsmWrite('.'); AsmWrite(s); AsmWriteLn(':');
  536. until not GetAdjacentTaiSymbol(hp);
  537. end;
  538. procedure TPPCMPWAssembler.WriteDataHeader(var s:string; isExported, isConst:boolean);
  539. // Returns in s the changed string
  540. var
  541. sym: string;
  542. replaced: boolean;
  543. begin
  544. sym:= s;
  545. replaced:= ReplaceForbiddenChars(s);
  546. if isExported then
  547. begin
  548. AsmWrite(#9'export'#9);
  549. AsmWrite(s);
  550. if isConst then
  551. AsmWrite(const_storage_class)
  552. else
  553. AsmWrite(var_storage_class);
  554. if replaced then
  555. begin
  556. AsmWrite(' => ''');
  557. AsmWrite(sym);
  558. AsmWrite('''');
  559. end;
  560. AsmLn;
  561. end;
  562. if not macos_direct_globals then
  563. begin
  564. {The actual section is here interrupted, by inserting a "tc" entry}
  565. AsmWriteLn(#9'toc');
  566. AsmWrite(#9'tc'#9);
  567. AsmWrite(s);
  568. AsmWrite('[TC], ');
  569. AsmWrite(s);
  570. if isConst then
  571. AsmWrite(const_storage_class)
  572. else
  573. AsmWrite(var_storage_class);
  574. AsmLn;
  575. {The interrupted section is here continued.}
  576. AsmWrite(#9'csect'#9);
  577. AsmWriteln(cur_CSECT_name+cur_CSECT_class);
  578. AsmWrite(PadTabs(s+':',#0));
  579. end
  580. else
  581. begin
  582. AsmWrite(#9'csect'#9);
  583. AsmWrite(s);
  584. AsmWrite('[TC]');
  585. end;
  586. AsmLn;
  587. end;
  588. var
  589. LasTSec : TAsmSectiontype;
  590. lastfileinfo : tfileposinfo;
  591. infile,
  592. lastinfile : tinputfile;
  593. const
  594. ait_const2str:array[aitconst_32bit..aitconst_8bit] of string[8]=
  595. (#9'dc.l'#9,#9'dc.w'#9,#9'dc.b'#9);
  596. procedure TPPCMPWAssembler.WriteTree(p:TAsmList);
  597. var
  598. s,
  599. prefix,
  600. suffix : string;
  601. hp : tai;
  602. hp1 : tailineinfo;
  603. counter,
  604. lines,
  605. InlineLevel : longint;
  606. i,j,l : longint;
  607. consttype : taiconst_type;
  608. found,
  609. do_line,DoNotSplitLine,
  610. quoted : boolean;
  611. sep : char;
  612. replaced : boolean;
  613. sin : single;
  614. d : double;
  615. begin
  616. if not assigned(p) then
  617. exit;
  618. InlineLevel:=0;
  619. { lineinfo is only needed for al_procedures (PFV) }
  620. do_line:=((cs_asm_source in current_settings.globalswitches) or
  621. (cs_lineinfo in current_settings.moduleswitches))
  622. and (p=current_asmdata.asmlists[al_procedures]);
  623. DoNotSplitLine:=false;
  624. hp:=tai(p.first);
  625. while assigned(hp) do
  626. begin
  627. if not(hp.typ in SkipLineInfo) and
  628. not DoNotSplitLine then
  629. begin
  630. hp1 := hp as tailineinfo;
  631. if do_line then
  632. begin
  633. { load infile }
  634. if lastfileinfo.fileindex<>hp1.fileinfo.fileindex then
  635. begin
  636. infile:=current_module.sourcefiles.get_file(hp1.fileinfo.fileindex);
  637. if assigned(infile) then
  638. begin
  639. { open only if needed !! }
  640. if (cs_asm_source in current_settings.globalswitches) then
  641. infile.open;
  642. end;
  643. { avoid unnecessary reopens of the same file !! }
  644. lastfileinfo.fileindex:=hp1.fileinfo.fileindex;
  645. { be sure to change line !! }
  646. lastfileinfo.line:=-1;
  647. end;
  648. { write source }
  649. if (cs_asm_source in current_settings.globalswitches) and
  650. assigned(infile) then
  651. begin
  652. if (infile<>lastinfile) then
  653. begin
  654. AsmWriteLn(target_asm.comment+'['+infile.name^+']');
  655. if assigned(lastinfile) then
  656. lastinfile.close;
  657. end;
  658. if (hp1.fileinfo.line<>lastfileinfo.line) and
  659. ((hp1.fileinfo.line<infile.maxlinebuf) or (InlineLevel>0)) then
  660. begin
  661. if (hp1.fileinfo.line<>0) and
  662. ((infile.linebuf^[hp1.fileinfo.line]>=0) or (InlineLevel>0)) then
  663. AsmWriteLn(target_asm.comment+'['+tostr(hp1.fileinfo.line)+'] '+
  664. fixline(infile.GetLineStr(hp1.fileinfo.line)));
  665. { set it to a negative value !
  666. to make that is has been read already !! PM }
  667. if (infile.linebuf^[hp1.fileinfo.line]>=0) then
  668. infile.linebuf^[hp1.fileinfo.line]:=-infile.linebuf^[hp1.fileinfo.line]-1;
  669. end;
  670. end;
  671. lastfileinfo:=hp1.fileinfo;
  672. lastinfile:=infile;
  673. end;
  674. end;
  675. DoNotSplitLine:=false;
  676. case hp.typ of
  677. ait_comment:
  678. begin
  679. AsmWrite(target_asm.comment);
  680. AsmWritePChar(tai_comment(hp).str);
  681. AsmLn;
  682. end;
  683. ait_regalloc,
  684. ait_tempalloc:
  685. ;
  686. ait_section:
  687. begin
  688. {if LasTSec<>sec_none then
  689. AsmWriteLn('_'+target_asm.secnames[LasTSec]+#9#9'ENDS');}
  690. if tai_section(hp).sectype<>sec_none then
  691. begin
  692. if tai_section(hp).sectype in [sec_data,sec_rodata,sec_bss] then
  693. cur_CSECT_class:= '[RW]'
  694. else if tai_section(hp).sectype in [sec_code] then
  695. cur_CSECT_class:= ''
  696. else
  697. cur_CSECT_class:= '[RO]';
  698. s:= tai_section(hp).name^;
  699. if s = '' then
  700. InternalError(2004101001); {Nameless sections should not occur on MPW}
  701. ReplaceForbiddenChars(s);
  702. cur_CSECT_name:= s;
  703. AsmLn;
  704. AsmWriteLn(#9+secnames[tai_section(hp).sectype]+' '+cur_CSECT_name+cur_CSECT_class);
  705. end;
  706. LasTSec:=tai_section(hp).sectype;
  707. end;
  708. ait_align:
  709. begin
  710. case tai_align(hp).aligntype of
  711. 1:AsmWriteLn(#9'align 0');
  712. 2:AsmWriteLn(#9'align 1');
  713. 4:AsmWriteLn(#9'align 2');
  714. otherwise internalerror(2002110302);
  715. end;
  716. end;
  717. ait_datablock: {Storage for global variables.}
  718. begin
  719. s:= tai_datablock(hp).sym.name;
  720. WriteDataHeader(s, tai_datablock(hp).is_global, false);
  721. if not macos_direct_globals then
  722. begin
  723. AsmWriteLn(#9'ds.b '+tostr(tai_datablock(hp).size));
  724. end
  725. else
  726. begin
  727. AsmWriteLn(PadTabs(s+':',#0)+'ds.b '+tostr(tai_datablock(hp).size));
  728. {TODO: ? PadTabs(s,#0) }
  729. end;
  730. end;
  731. ait_const:
  732. begin
  733. consttype:=tai_const(hp).consttype;
  734. case consttype of
  735. aitconst_128bit:
  736. begin
  737. internalerror(200404291);
  738. end;
  739. aitconst_64bit:
  740. begin
  741. if assigned(tai_const(hp).sym) then
  742. internalerror(200404292);
  743. AsmWrite(ait_const2str[aitconst_32bit]);
  744. if target_info.endian = endian_little then
  745. begin
  746. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  747. AsmWrite(',');
  748. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  749. end
  750. else
  751. begin
  752. AsmWrite(tostr(longint(hi(tai_const(hp).value))));
  753. AsmWrite(',');
  754. AsmWrite(tostr(longint(lo(tai_const(hp).value))));
  755. end;
  756. AsmLn;
  757. end;
  758. aitconst_uleb128bit,
  759. aitconst_sleb128bit,
  760. aitconst_32bit,
  761. aitconst_16bit,
  762. aitconst_8bit,
  763. aitconst_rva_symbol,
  764. aitconst_indirect_symbol :
  765. begin
  766. AsmWrite(ait_const2str[consttype]);
  767. l:=0;
  768. repeat
  769. if assigned(tai_const(hp).sym) then
  770. begin
  771. if assigned(tai_const(hp).endsym) then
  772. begin
  773. if (tai_const(hp).endsym.typ = AT_FUNCTION) and use_PR then
  774. AsmWrite('.');
  775. s:=tai_const(hp).endsym.name;
  776. ReplaceForbiddenChars(s);
  777. AsmWrite(s);
  778. inc(l,length(s));
  779. if tai_const(hp).endsym.typ = AT_FUNCTION then
  780. begin
  781. if use_PR then
  782. AsmWrite('[PR]')
  783. else
  784. AsmWrite('[DS]');
  785. end;
  786. AsmWrite('-');
  787. inc(l,5); {Approx 5 extra, no need to be exactly}
  788. end;
  789. if (tai_const(hp).sym.typ = AT_FUNCTION) and use_PR then
  790. AsmWrite('.');
  791. s:= tai_const(hp).sym.name;
  792. ReplaceForbiddenChars(s);
  793. AsmWrite(s);
  794. inc(l,length(s));
  795. if tai_const(hp).sym.typ = AT_FUNCTION then
  796. begin
  797. if use_PR then
  798. AsmWrite('[PR]')
  799. else
  800. AsmWrite('[DS]');
  801. end;
  802. inc(l,5); {Approx 5 extra, no need to be exactly}
  803. if tai_const(hp).value > 0 then
  804. s:= '+'+tostr(tai_const(hp).value)
  805. else if tai_const(hp).value < 0 then
  806. s:= '-'+tostr(tai_const(hp).value)
  807. else
  808. s:= '';
  809. if s<>'' then
  810. begin
  811. AsmWrite(s);
  812. inc(l,length(s));
  813. end;
  814. end
  815. else
  816. begin
  817. s:= tostr(tai_const(hp).value);
  818. AsmWrite(s);
  819. inc(l,length(s));
  820. end;
  821. if (l>line_length) or
  822. (hp.next=nil) or
  823. (tai(hp.next).typ<>ait_const) or
  824. (tai_const(hp.next).consttype<>consttype) then
  825. break;
  826. hp:=tai(hp.next);
  827. AsmWrite(',');
  828. until false;
  829. AsmLn;
  830. end;
  831. end;
  832. end;
  833. ait_real_64bit :
  834. begin
  835. AsmWriteLn(target_asm.comment+'value: '+double2str(tai_real_64bit(hp).value));
  836. d:=tai_real_64bit(hp).value;
  837. { swap the values to correct endian if required }
  838. if source_info.endian <> target_info.endian then
  839. swap64bitarray(t64bitarray(d));
  840. AsmWrite(#9'dc.b'#9);
  841. begin
  842. for i:=0 to 7 do
  843. begin
  844. if i<>0 then
  845. AsmWrite(',');
  846. AsmWrite(tostr(t64bitarray(d)[i]));
  847. end;
  848. end;
  849. AsmLn;
  850. end;
  851. ait_real_32bit :
  852. begin
  853. AsmWriteLn(target_asm.comment+'value: '+single2str(tai_real_32bit(hp).value));
  854. sin:=tai_real_32bit(hp).value;
  855. { swap the values to correct endian if required }
  856. if source_info.endian <> target_info.endian then
  857. swap32bitarray(t32bitarray(sin));
  858. AsmWrite(#9'dc.b'#9);
  859. for i:=0 to 3 do
  860. begin
  861. if i<>0 then
  862. AsmWrite(',');
  863. AsmWrite(tostr(t32bitarray(sin)[i]));
  864. end;
  865. AsmLn;
  866. end;
  867. ait_string:
  868. begin
  869. {NOTE When a single quote char is encountered, it is
  870. replaced with a numeric ascii value. It could also
  871. have been replaced with the escape seq of double quotes.
  872. Backslash seems to be used as an escape char, although
  873. this is not mentioned in the PPCAsm documentation.}
  874. counter := 0;
  875. lines := tai_string(hp).len div line_length;
  876. { separate lines in different parts }
  877. if tai_string(hp).len > 0 then
  878. begin
  879. for j := 0 to lines-1 do
  880. begin
  881. AsmWrite(#9'dc.b'#9);
  882. quoted:=false;
  883. for i:=counter to counter+line_length-1 do
  884. begin
  885. { it is an ascii character. }
  886. if (ord(tai_string(hp).str[i])>31) and
  887. (ord(tai_string(hp).str[i])<128) and
  888. (tai_string(hp).str[i]<>'''') and
  889. (tai_string(hp).str[i]<>'\') then
  890. begin
  891. if not(quoted) then
  892. begin
  893. if i>counter then
  894. AsmWrite(',');
  895. AsmWrite('''');
  896. end;
  897. AsmWrite(tai_string(hp).str[i]);
  898. quoted:=true;
  899. end { if > 31 and < 128 and ord('"') }
  900. else
  901. begin
  902. if quoted then
  903. AsmWrite('''');
  904. if i>counter then
  905. AsmWrite(',');
  906. quoted:=false;
  907. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  908. end;
  909. end; { end for i:=0 to... }
  910. if quoted then AsmWrite('''');
  911. AsmLn;
  912. counter := counter+line_length;
  913. end; { end for j:=0 ... }
  914. { do last line of lines }
  915. if counter < tai_string(hp).len then
  916. AsmWrite(#9'dc.b'#9);
  917. quoted:=false;
  918. for i:=counter to tai_string(hp).len-1 do
  919. begin
  920. { it is an ascii character. }
  921. if (ord(tai_string(hp).str[i])>31) and
  922. (ord(tai_string(hp).str[i])<128) and
  923. (tai_string(hp).str[i]<>'''') and
  924. (tai_string(hp).str[i]<>'\') then
  925. begin
  926. if not(quoted) then
  927. begin
  928. if i>counter then
  929. AsmWrite(',');
  930. AsmWrite('''');
  931. end;
  932. AsmWrite(tai_string(hp).str[i]);
  933. quoted:=true;
  934. end { if > 31 and < 128 and " }
  935. else
  936. begin
  937. if quoted then
  938. AsmWrite('''');
  939. if i>counter then
  940. AsmWrite(',');
  941. quoted:=false;
  942. AsmWrite(tostr(ord(tai_string(hp).str[i])));
  943. end;
  944. end; { end for i:=0 to... }
  945. if quoted then
  946. AsmWrite('''');
  947. end;
  948. AsmLn;
  949. end;
  950. ait_label:
  951. begin
  952. if tai_label(hp).labsym.is_used then
  953. begin
  954. s:= tai_label(hp).labsym.name;
  955. if s[1] = '@' then
  956. begin
  957. ReplaceForbiddenChars(s);
  958. //Local labels:
  959. AsmWriteLn(s+':')
  960. end
  961. else
  962. begin
  963. //Procedure entry points:
  964. if not macos_direct_globals then
  965. begin
  966. WriteDataHeader(s, tai_label(hp).is_global, true);
  967. end
  968. else
  969. begin
  970. ReplaceForbiddenChars(s);
  971. AsmWrite(#9'csect'#9); AsmWrite(s);
  972. AsmWriteLn('[TC]');
  973. AsmWriteLn(PadTabs(s+':',#0));
  974. end;
  975. end;
  976. end;
  977. end;
  978. ait_symbol:
  979. begin
  980. if tai_symbol(hp).sym.typ=AT_FUNCTION then
  981. WriteProcedureHeader(hp)
  982. else if tai_symbol(hp).sym.typ=AT_DATA then
  983. begin
  984. s:= tai_symbol(hp).sym.name;
  985. WriteDataHeader(s, tai_symbol(hp).is_global, true);
  986. if macos_direct_globals then
  987. begin
  988. AsmWrite(s);
  989. AsmWriteLn(':');
  990. end;
  991. end
  992. else
  993. InternalError(2003071301);
  994. end;
  995. ait_symbol_end:
  996. ;
  997. ait_instruction:
  998. WriteInstruction(hp);
  999. ait_stab,
  1000. ait_force_line,
  1001. ait_function_name : ;
  1002. ait_cutobject :
  1003. begin
  1004. InternalError(2004101101); {Smart linking is done transparently by the MPW linker.}
  1005. end;
  1006. ait_marker :
  1007. begin
  1008. if tai_marker(hp).kind=mark_InlineStart then
  1009. inc(InlineLevel)
  1010. else if tai_marker(hp).kind=mark_InlineEnd then
  1011. dec(InlineLevel);
  1012. end;
  1013. else
  1014. internalerror(2002110303);
  1015. end;
  1016. hp:=tai(hp.next);
  1017. end;
  1018. end;
  1019. var
  1020. currentasmlist : TExternalAssembler;
  1021. procedure writeexternal(p:tasmsymbol);
  1022. var
  1023. s:string;
  1024. replaced: boolean;
  1025. begin
  1026. if tasmsymbol(p).bind=AB_EXTERNAL then
  1027. begin
  1028. //Writeln('ZZZ ',p.name,' ',p.classname,' ',Ord(tasmsymbol(p).typ));
  1029. s:= p.name;
  1030. replaced:= ReplaceForbiddenChars(s);
  1031. with currentasmlist do
  1032. case tasmsymbol(p).typ of
  1033. AT_FUNCTION:
  1034. begin
  1035. AsmWrite(#9'import'#9'.');
  1036. AsmWrite(s);
  1037. if use_PR then
  1038. AsmWrite('[PR]');
  1039. if replaced then
  1040. begin
  1041. AsmWrite(' <= ''.');
  1042. AsmWrite(p.name);
  1043. if use_PR then
  1044. AsmWrite('[PR]''')
  1045. else
  1046. AsmWrite('''');
  1047. end;
  1048. AsmLn;
  1049. AsmWrite(#9'import'#9);
  1050. AsmWrite(s);
  1051. AsmWrite('[DS]');
  1052. if replaced then
  1053. begin
  1054. AsmWrite(' <= ''');
  1055. AsmWrite(p.name);
  1056. AsmWrite('[DS]''');
  1057. end;
  1058. AsmLn;
  1059. AsmWriteLn(#9'toc');
  1060. AsmWrite(#9'tc'#9);
  1061. AsmWrite(s);
  1062. AsmWrite('[TC],');
  1063. AsmWrite(s);
  1064. AsmWriteLn('[DS]');
  1065. end;
  1066. AT_DATA:
  1067. begin
  1068. AsmWrite(#9'import'#9);
  1069. AsmWrite(s);
  1070. AsmWrite(var_storage_class);
  1071. if replaced then
  1072. begin
  1073. AsmWrite(' <= ''');
  1074. AsmWrite(p.name);
  1075. AsmWrite('''');
  1076. end;
  1077. AsmLn;
  1078. AsmWriteLn(#9'toc');
  1079. AsmWrite(#9'tc'#9);
  1080. AsmWrite(s);
  1081. AsmWrite('[TC],');
  1082. AsmWrite(s);
  1083. AsmWriteLn(var_storage_class);
  1084. end
  1085. else
  1086. InternalError(2003090901);
  1087. end;
  1088. end;
  1089. end;
  1090. procedure TPPCMPWAssembler.WriteExternals;
  1091. var
  1092. i : longint;
  1093. begin
  1094. currentasmlist:=self;
  1095. // current_asmdata.asmsymboldict.foreach_static(@writeexternal,nil);
  1096. for i:=0 to current_asmdata.AsmSymbolDict.Count-1 do
  1097. begin
  1098. writeexternal(tasmsymbol(current_asmdata.AsmSymbolDict[i]));
  1099. end;
  1100. end;
  1101. function TPPCMPWAssembler.DoAssemble : boolean;
  1102. var f : file;
  1103. begin
  1104. DoAssemble:=Inherited DoAssemble;
  1105. (*
  1106. { masm does not seem to recognize specific extensions and uses .obj allways PM }
  1107. if (target_asm.id = as_i386_masm) then
  1108. begin
  1109. if not(cs_asm_extern in current_settings.globalswitches) then
  1110. begin
  1111. if Not FileExists(objfile) and
  1112. FileExists(ForceExtension(objfile,'.obj')) then
  1113. begin
  1114. Assign(F,ForceExtension(objfile,'.obj'));
  1115. Rename(F,objfile);
  1116. end;
  1117. end
  1118. else
  1119. AsmRes.AddAsmCommand('mv',ForceExtension(objfile,'.obj')+' '+objfile,objfile);
  1120. end;
  1121. *)
  1122. end;
  1123. procedure TPPCMPWAssembler.WriteAsmFileHeader;
  1124. begin
  1125. (*
  1126. AsmWriteLn(#9'.386p');
  1127. { masm 6.11 does not seem to like LOCALS PM }
  1128. if (target_asm.id = as_i386_tasm) then
  1129. begin
  1130. AsmWriteLn(#9'LOCALS '+target_asm.labelprefix);
  1131. end;
  1132. AsmWriteLn('DGROUP'#9'GROUP'#9'_BSS,_DATA');
  1133. AsmWriteLn(#9'ASSUME'#9'CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP');
  1134. AsmLn;
  1135. *)
  1136. AsmWriteLn(#9'string asis'); {Interpret strings just to be the content between the quotes.}
  1137. AsmWriteLn(#9'aligning off'); {We do our own aligning.}
  1138. AsmLn;
  1139. end;
  1140. procedure TPPCMPWAssembler.WriteAsmList;
  1141. var
  1142. hal : tasmlisttype;
  1143. begin
  1144. {$ifdef EXTDEBUG}
  1145. if assigned(current_module.mainsource) then
  1146. comment(v_info,'Start writing MPW-styled assembler output for '+current_module.mainsource^);
  1147. {$endif}
  1148. LasTSec:=sec_none;
  1149. WriteAsmFileHeader;
  1150. WriteExternals;
  1151. for hal:=low(TasmlistType) to high(TasmlistType) do
  1152. begin
  1153. AsmWriteLn(target_asm.comment+'Begin asmlist '+AsmListTypeStr[hal]);
  1154. writetree(current_asmdata.asmlists[hal]);
  1155. AsmWriteLn(target_asm.comment+'End asmlist '+AsmListTypeStr[hal]);
  1156. end;
  1157. AsmWriteLn(#9'end');
  1158. AsmLn;
  1159. {$ifdef EXTDEBUG}
  1160. if assigned(current_module.mainsource) then
  1161. comment(v_info,'Done writing MPW-styled assembler output for '+current_module.mainsource^);
  1162. {$endif EXTDEBUG}
  1163. end;
  1164. {*****************************************************************************
  1165. Initialize
  1166. *****************************************************************************}
  1167. const
  1168. as_powerpc_mpw_info : tasminfo =
  1169. (
  1170. id : as_powerpc_mpw;
  1171. idtxt : 'MPW';
  1172. asmbin : 'PPCAsm';
  1173. asmcmd : '-case on $ASM -o $OBJ';
  1174. supported_target : system_any; { what should I write here ?? }
  1175. flags : [af_allowdirect,af_needar,af_smartlink_sections,af_labelprefix_only_inside_procedure];
  1176. labelprefix : '@';
  1177. comment : '; ';
  1178. );
  1179. initialization
  1180. RegisterAssembler(as_powerpc_mpw_info,TPPCMPWAssembler);
  1181. end.