agppcmpw.pas 40 KB

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