agppcmpw.pas 38 KB

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