agppcmpw.pas 38 KB

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