agppcmpw.pas 44 KB

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