ag386att.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements an asmoutput class for i386 AT&T syntax
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. { This unit implements an asmoutput class for i386 AT&T syntax
  19. }
  20. unit ag386att;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. cclasses,cpubase,
  25. globals,
  26. aasmbase,aasmtai,aasmcpu,assemble,aggas;
  27. type
  28. T386ATTAssembler=class(TGNUassembler)
  29. public
  30. procedure WriteInstruction(hp: tai);override;
  31. end;
  32. TAttSuffix = (AttSufNONE,AttSufINT,AttSufFPU,AttSufFPUint);
  33. const
  34. gas_op2str:op2strtable={$i i386att.inc}
  35. gas_needsuffix:array[tasmop] of TAttSuffix={$i i386atts.inc}
  36. gas_reg2str : reg2strtable = ('',
  37. '%eax','%ecx','%edx','%ebx','%esp','%ebp','%esi','%edi',
  38. '%ax','%cx','%dx','%bx','%sp','%bp','%si','%di',
  39. '%al','%cl','%dl','%bl','%ah','%ch','%bh','%dh',
  40. '%cs','%ds','%es','%ss','%fs','%gs',
  41. '%st','%st(0)','%st(1)','%st(2)','%st(3)','%st(4)','%st(5)','%st(6)','%st(7)',
  42. '%dr0','%dr1','%dr2','%dr3','%dr6','%dr7',
  43. '%cr0','%cr2','%cr3','%cr4',
  44. '%tr3','%tr4','%tr5','%tr6','%tr7',
  45. '%mm0','%mm1','%mm2','%mm3','%mm4','%mm5','%mm6','%mm7',
  46. '%xmm0','%xmm1','%xmm2','%xmm3','%xmm4','%xmm5','%xmm6','%xmm7'
  47. );
  48. gas_opsize2str : array[topsize] of string[2] = ('',
  49. 'b','w','l','bw','bl','wl',
  50. 's','l','q',
  51. 's','l','t','d','q','v',
  52. '','',''
  53. );
  54. implementation
  55. uses
  56. cutils,systems,
  57. verbose;
  58. function getreferencestring(var ref : treference) : string;
  59. var
  60. s : string;
  61. begin
  62. with ref do
  63. begin
  64. inc(offset,offsetfixup);
  65. offsetfixup:=0;
  66. { have we a segment prefix ? }
  67. { These are probably not correctly handled under GAS }
  68. { should be replaced by coding the segment override }
  69. { directly! - DJGPP FAQ }
  70. if segment<>R_NO then
  71. s:=gas_reg2str[segment]+':'
  72. else
  73. s:='';
  74. if assigned(symbol) then
  75. s:=s+symbol.name;
  76. if offset<0 then
  77. s:=s+tostr(offset)
  78. else
  79. if (offset>0) then
  80. begin
  81. if assigned(symbol) then
  82. s:=s+'+'+tostr(offset)
  83. else
  84. s:=s+tostr(offset);
  85. end
  86. else if (index=R_NO) and (base=R_NO) and not assigned(symbol) then
  87. s:=s+'0';
  88. if (index<>R_NO) and (base=R_NO) then
  89. begin
  90. s:=s+'(,'+gas_reg2str[index];
  91. if scalefactor<>0 then
  92. s:=s+','+tostr(scalefactor)+')'
  93. else
  94. s:=s+')';
  95. end
  96. else
  97. if (index=R_NO) and (base<>R_NO) then
  98. s:=s+'('+gas_reg2str[base]+')'
  99. else
  100. if (index<>R_NO) and (base<>R_NO) then
  101. begin
  102. s:=s+'('+gas_reg2str[base]+','+gas_reg2str[index];
  103. if scalefactor<>0 then
  104. s:=s+','+tostr(scalefactor)+')'
  105. else
  106. s := s+')';
  107. end;
  108. end;
  109. getreferencestring:=s;
  110. end;
  111. function getopstr(const o:toper) : string;
  112. var
  113. hs : string;
  114. begin
  115. case o.typ of
  116. top_reg :
  117. getopstr:=gas_reg2str[o.reg];
  118. top_ref :
  119. getopstr:=getreferencestring(o.ref^);
  120. top_const :
  121. getopstr:='$'+tostr(longint(o.val));
  122. top_symbol :
  123. begin
  124. if assigned(o.sym) then
  125. hs:='$'+o.sym.name
  126. else
  127. hs:='$';
  128. if o.symofs>0 then
  129. hs:=hs+'+'+tostr(o.symofs)
  130. else
  131. if o.symofs<0 then
  132. hs:=hs+tostr(o.symofs)
  133. else
  134. if not(assigned(o.sym)) then
  135. hs:=hs+'0';
  136. getopstr:=hs;
  137. end;
  138. else
  139. internalerror(10001);
  140. end;
  141. end;
  142. function getopstr_jmp(const o:toper) : string;
  143. var
  144. hs : string;
  145. begin
  146. case o.typ of
  147. top_reg :
  148. getopstr_jmp:='*'+gas_reg2str[o.reg];
  149. top_ref :
  150. getopstr_jmp:='*'+getreferencestring(o.ref^);
  151. top_const :
  152. getopstr_jmp:=tostr(longint(o.val));
  153. top_symbol :
  154. begin
  155. hs:=o.sym.name;
  156. if o.symofs>0 then
  157. hs:=hs+'+'+tostr(o.symofs)
  158. else
  159. if o.symofs<0 then
  160. hs:=hs+tostr(o.symofs);
  161. getopstr_jmp:=hs;
  162. end;
  163. else
  164. internalerror(10001);
  165. end;
  166. end;
  167. {****************************************************************************
  168. TI386ATTASMOUTPUT
  169. ****************************************************************************}
  170. procedure T386AttAssembler. WriteInstruction(hp: tai);
  171. var
  172. op : tasmop;
  173. s : string;
  174. sep : char;
  175. calljmp : boolean;
  176. i : integer;
  177. begin
  178. if hp.typ <> ait_instruction then exit;
  179. taicpu(hp).SetOperandOrder(op_att);
  180. op:=taicpu(hp).opcode;
  181. calljmp:=is_calljmp(op);
  182. { call maybe not translated to call }
  183. s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition];
  184. { suffix needed ? fnstsw,fldcw don't support suffixes
  185. with binutils 2.9.5 under linux }
  186. if (not calljmp) and
  187. (gas_needsuffix[op]<>AttSufNONE) and
  188. (op<>A_FNSTSW) and (op<>A_FSTSW) and
  189. (op<>A_FNSTCW) and (op<>A_FSTCW) and
  190. (op<>A_FLDCW) and not(
  191. (taicpu(hp).oper[0].typ=top_reg) and
  192. (taicpu(hp).oper[0].reg in [R_ST..R_ST7])
  193. ) then
  194. s:=s+gas_opsize2str[taicpu(hp).opsize];
  195. { process operands }
  196. if taicpu(hp).ops<>0 then
  197. begin
  198. { call and jmp need an extra handling }
  199. { this code is only called if jmp isn't a labeled instruction }
  200. { quick hack to overcome a problem with manglednames=255 chars }
  201. if calljmp then
  202. begin
  203. AsmWrite(s+#9);
  204. s:=getopstr_jmp(taicpu(hp).oper[0]);
  205. end
  206. else
  207. begin
  208. for i:=0 to taicpu(hp).ops-1 do
  209. begin
  210. if i=0 then
  211. sep:=#9
  212. else
  213. sep:=',';
  214. s:=s+sep+getopstr(taicpu(hp).oper[i])
  215. end;
  216. end;
  217. end;
  218. AsmWriteLn(s);
  219. end;
  220. {*****************************************************************************
  221. Initialize
  222. *****************************************************************************}
  223. const
  224. as_i386_as_info : tasminfo =
  225. (
  226. id : as_gas;
  227. idtxt : 'AS';
  228. asmbin : 'as';
  229. asmcmd : '-o $OBJ $ASM';
  230. supported_target : system_any;
  231. outputbinary: false;
  232. allowdirect : true;
  233. needar : true;
  234. labelprefix_only_inside_procedure : false;
  235. labelprefix : '.L';
  236. comment : '# ';
  237. secnames : ('',
  238. '.text','.data','.bss',
  239. '','','','','','',
  240. '.stab','.stabstr','COMMON')
  241. );
  242. as_i386_as_aout_info : tasminfo =
  243. (
  244. id : as_i386_as_aout;
  245. idtxt : 'AS_AOUT';
  246. asmbin : 'as';
  247. asmcmd : '-o $OBJ $ASM';
  248. supported_target : system_i386_os2;
  249. outputbinary: false;
  250. allowdirect : true;
  251. needar : true;
  252. labelprefix_only_inside_procedure : false;
  253. labelprefix : 'L';
  254. comment : '# ';
  255. secnames : ('',
  256. '.text','.data','.bss',
  257. '','','','','','',
  258. '.stab','.stabstr','COMMON')
  259. );
  260. as_i386_asw_info : tasminfo =
  261. (
  262. id : as_i386_asw;
  263. idtxt : 'ASW';
  264. asmbin : 'asw';
  265. asmcmd : '-o $OBJ $ASM';
  266. supported_target : system_i386_win32;
  267. outputbinary: false;
  268. allowdirect : true;
  269. needar : true;
  270. labelprefix_only_inside_procedure : false;
  271. labelprefix : '.L';
  272. comment : '# ';
  273. secnames : ('',
  274. '.text','.data','.section .bss',
  275. '.section .idata$2','.section .idata$4','.section .idata$5',
  276. '.section .idata$6','.section .idata$7','.section .edata',
  277. '.stab','.stabstr','COMMON')
  278. );
  279. initialization
  280. RegisterAssembler(as_i386_as_info,T386ATTAssembler);
  281. RegisterAssembler(as_i386_as_aout_info,T386ATTAssembler);
  282. RegisterAssembler(as_i386_asw_info,T386ATTAssembler);
  283. end.
  284. {
  285. $Log$
  286. Revision 1.26 2002-08-12 15:08:40 carl
  287. + stab register indexes for powerpc (moved from gdb to cpubase)
  288. + tprocessor enumeration moved to cpuinfo
  289. + linker in target_info is now a class
  290. * many many updates for m68k (will soon start to compile)
  291. - removed some ifdef or correct them for correct cpu
  292. Revision 1.25 2002/07/26 21:15:42 florian
  293. * rewrote the system handling
  294. Revision 1.24 2002/07/07 09:52:33 florian
  295. * powerpc target fixed, very simple units can be compiled
  296. * some basic stuff for better callparanode handling, far from being finished
  297. Revision 1.23 2002/07/01 18:46:29 peter
  298. * internal linker
  299. * reorganized aasm layer
  300. Revision 1.22 2002/05/18 13:34:21 peter
  301. * readded missing revisions
  302. Revision 1.21 2002/05/16 19:46:49 carl
  303. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  304. + try to fix temp allocation (still in ifdef)
  305. + generic constructor calls
  306. + start of tassembler / tmodulebase class cleanup
  307. Revision 1.19 2002/05/12 16:53:16 peter
  308. * moved entry and exitcode to ncgutil and cgobj
  309. * foreach gets extra argument for passing local data to the
  310. iterator function
  311. * -CR checks also class typecasts at runtime by changing them
  312. into as
  313. * fixed compiler to cycle with the -CR option
  314. * fixed stabs with elf writer, finally the global variables can
  315. be watched
  316. * removed a lot of routines from cga unit and replaced them by
  317. calls to cgobj
  318. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  319. u32bit then the other is typecasted also to u32bit without giving
  320. a rangecheck warning/error.
  321. * fixed pascal calling method with reversing also the high tree in
  322. the parast, detected by tcalcst3 test
  323. Revision 1.18 2002/04/15 19:12:10 carl
  324. + target_info.size_of_pointer -> pointer_size
  325. + some cleanup of unused types/variables
  326. * move several constants from cpubase to their specific units
  327. (where they are used)
  328. + att_Reg2str -> gas_reg2str
  329. + int_reg2str -> std_reg2str
  330. Revision 1.17 2002/04/14 16:58:04 carl
  331. + move into aggas most of the stuff non-processor specific
  332. Revision 1.16 2002/04/10 08:07:55 jonas
  333. * fix for the ie9999 under Linux (patch from Peter)
  334. Revision 1.15 2002/04/04 19:06:06 peter
  335. * removed unused units
  336. * use tlocation.size in cg.a_*loc*() routines
  337. Revision 1.14 2002/04/04 18:26:55 carl
  338. + added wdosx patch from Pavel
  339. Revision 1.13 2002/04/02 17:11:33 peter
  340. * tlocation,treference update
  341. * LOC_CONSTANT added for better constant handling
  342. * secondadd splitted in multiple routines
  343. * location_force_reg added for loading a location to a register
  344. of a specified size
  345. * secondassignment parses now first the right and then the left node
  346. (this is compatible with Kylix). This saves a lot of push/pop especially
  347. with string operations
  348. * adapted some routines to use the new cg methods
  349. }