1 { 2 Copyright (c) 1999-2003 by Florian Klaempfl 3 4 This unit implements an asmoutput class for SPARC AT&T syntax 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 **************************************************************************** 21 } 22 unit cpugas; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 cpubase,systems, 30 aasmtai,aasmdata,aasmcpu,assemble,aggas, 31 cgutils,globtype; 32 33 type 34 TGasSPARC=class(TGnuAssembler) 35 constructor CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); override; 36 {# Constructs the command line for calling the assembler } MakeCmdLinenull37 function MakeCmdLine: TCmdStr; override; 38 end; 39 40 TSPARCInstrWriter=class(TCPUInstrWriter) 41 procedure WriteInstruction(hp:Tai);override; GetReferenceStringnull42 function GetReferenceString(var ref : TReference):string; getopstrnull43 function getopstr(const Oper:TOper):string; 44 end; 45 46 implementation 47 48 uses 49 cutils,globals,cpuinfo,procinfo, 50 verbose,itcpugas,cgbase; 51 52 53 {****************************************************************************} 54 { GNU PPC Assembler writer } 55 {****************************************************************************} 56 57 constructor TGasSPARC.CreateWithWriter(info: pasminfo; wr: TExternalAssemblerOutputFile; freewriter, smart: boolean); 58 begin 59 inherited; 60 InstrWriter := TSPARCInstrWriter.create(self); 61 end; 62 63 TGasSPARC.MakeCmdLinenull64 function TGasSPARC.MakeCmdLine: TCmdStr; 65 begin 66 result := Inherited MakeCmdLine; 67 68 { ARCH selection } 69 // Note for casual readers: gas (GNU as) uses -Av7, -Av8, -Av9 etc. on SPARC, 70 // rather than variants of the -m option used by most other CPUs. Solaris as 71 // uses -xarch=v7, -xarch=v8 etc., that form is not supported here since there 72 // are probably other incompatibilties between the GNU and Solaris binutils 73 // that need to be reviewed. 74 // 75 // v9 is required as the default since the RTL started using membar at 2.2.2. 76 case current_settings.cputype of 77 {$ifdef SPARC} 78 cpu_SPARC_V7: Replace(result,'$ARCH','-Av7'); 79 cpu_SPARC_V8: Replace(result,'$ARCH','-Av8'); 80 {$endif SPARC} 81 cpu_SPARC_V9: Replace(result,'$ARCH','-Av9'); 82 else 83 Replace(result,'$ARCH','-Av9') 84 end 85 end; 86 87 TSPARCInstrWriter.GetReferenceStringnull88 function TSPARCInstrWriter.GetReferenceString(var ref:TReference):string; 89 begin 90 result:=''; 91 if assigned(ref.symbol) then 92 begin 93 result:=ref.symbol.name; 94 if assigned(ref.relsymbol) then 95 result:=result+'-'+ref.relsymbol.name; 96 end; 97 if (ref.offset<0) then 98 result:=result+tostr(ref.offset) 99 else if (ref.offset>0) then 100 begin 101 if assigned(ref.symbol) then 102 result:=result+'+'; 103 result:=result+tostr(ref.offset); 104 end 105 { asmreader appears to treat literal numbers as references } 106 else if (ref.symbol=nil) and (ref.base=NR_NO) and (ref.index=NR_NO) then 107 result:='0'; 108 109 case ref.refaddr of 110 addr_high: 111 result:='%hi('+result+')'; 112 addr_low: 113 result:='%lo('+result+')'; 114 end; 115 116 if assigned(ref.symbol) or (ref.offset<>0) then 117 begin 118 if (ref.base<>NR_NO) then 119 begin 120 if (ref.index<>NR_NO) then 121 InternalError(2013013001); 122 if (result[1]='-') then 123 result:=gas_regname(ref.base)+result 124 else 125 result:=gas_regname(ref.base)+'+'+result; 126 end 127 else if (ref.index<>NR_NO) then 128 InternalError(2013122501); 129 end 130 else 131 begin 132 if (ref.base<>NR_NO) then 133 begin 134 result:=gas_regname(ref.base); 135 if (ref.index<>NR_NO) then 136 result:=result+'+'+gas_regname(ref.index); 137 end 138 else if (ref.index<>NR_NO) then 139 result:=gas_regname(ref.index); 140 end; 141 end; 142 143 TSPARCInstrWriter.getopstrnull144 function TSPARCInstrWriter.getopstr(const Oper:TOper):string; 145 begin 146 with Oper do 147 case typ of 148 top_reg: 149 getopstr:=gas_regname(reg); 150 top_const: 151 getopstr:=tostr(longint(val)); 152 top_ref: 153 if (oper.ref^.refaddr in [addr_no,addr_pic]) or 154 ((oper.ref^.refaddr=addr_low) and ((oper.ref^.base<>NR_NO) or 155 (oper.ref^.index<>NR_NO))) then 156 getopstr:='['+getreferencestring(ref^)+']' 157 else 158 getopstr:=getreferencestring(ref^); 159 else 160 internalerror(10001); 161 end; 162 end; 163 164 165 procedure TSPARCInstrWriter.WriteInstruction(hp:Tai); 166 167 procedure writePseudoInstruction(opc: TAsmOp); 168 begin 169 if (taicpu(hp).ops<>2) or 170 (taicpu(hp).oper[0]^.typ<>top_reg) or 171 (taicpu(hp).oper[1]^.typ<>top_reg) then 172 internalerror(200401045); 173 { Fxxxs %f<even>,%f<even> } 174 owner.writer.AsmWriteln(#9+std_op2str[opc]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^)); 175 { FMOVs %f<odd>,%f<odd> } 176 inc(taicpu(hp).oper[0]^.reg); 177 inc(taicpu(hp).oper[1]^.reg); 178 owner.writer.AsmWriteln(#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^)); 179 dec(taicpu(hp).oper[0]^.reg); 180 dec(taicpu(hp).oper[1]^.reg); 181 end; 182 183 var 184 Op:TAsmOp; 185 s:String; 186 i:Integer; 187 begin 188 if hp.typ<>ait_instruction then 189 exit; 190 op:=taicpu(hp).opcode; 191 if (op=A_Bxx) and (taicpu(hp).condition in floatAsmConds) then 192 op:=A_FBxx; 193 { translate pseudoops, this should be move to a separate pass later, so it's done before 194 peephole optimization } 195 case op of 196 A_FABSd: 197 writePseudoInstruction(A_FABSs); 198 199 A_FMOVd: 200 writePseudoInstruction(A_FMOVs); 201 202 A_FNEGd: 203 writePseudoInstruction(A_FNEGs); 204 205 else 206 begin 207 { call maybe not translated to call } 208 s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition]; 209 if taicpu(hp).delayslot_annulled then 210 s:=s+',a'; 211 if taicpu(hp).ops>0 then 212 begin 213 s:=s+#9+getopstr(taicpu(hp).oper[0]^); 214 for i:=1 to taicpu(hp).ops-1 do 215 s:=s+','+getopstr(taicpu(hp).oper[i]^); 216 end; 217 owner.writer.AsmWriteLn(s); 218 end; 219 end; 220 end; 221 222 223 const 224 as_sparc_as_info : tasminfo = 225 ( 226 id : as_gas; 227 idtxt : 'AS'; 228 asmbin : 'as'; 229 {$ifdef FPC_SPARC_V8_ONLY} 230 asmcmd : '$PIC -o $OBJ $EXTRAOPT $ASM'; 231 {$else} 232 asmcmd : '$ARCH $PIC -32 -o $OBJ $EXTRAOPT $ASM'; 233 {$endif} 234 supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded]; 235 flags : [af_needar,af_smartlink_sections]; 236 labelprefix : '.L'; 237 comment : '# '; 238 dollarsign: '$'; 239 ); 240 241 as_sparc_gas_info : tasminfo = 242 ( 243 id : as_ggas; 244 idtxt : 'GAS'; 245 asmbin : 'gas'; 246 asmcmd : '$ARCH $PIC -o $OBJ $EXTRAOPT $ASM'; 247 supported_targets : [system_sparc_solaris,system_sparc_linux,system_sparc_embedded]; 248 flags : [af_needar,af_smartlink_sections]; 249 labelprefix : '.L'; 250 comment : '# '; 251 dollarsign: '$'; 252 ); 253 254 as_sparc64_as_info : tasminfo = 255 ( 256 id : as_gas; 257 idtxt : 'AS'; 258 asmbin : 'as'; 259 {$ifdef FPC_SPARC_V8_ONLY} 260 asmcmd : '$PIC -o $OBJ $EXTRAOPT $ASM'; 261 {$else} 262 asmcmd : '$ARCH $PIC -o $OBJ $EXTRAOPT $ASM'; 263 {$endif} 264 supported_targets : [system_sparc64_linux]; 265 flags : [af_needar,af_smartlink_sections]; 266 labelprefix : '.L'; 267 comment : '# '; 268 dollarsign: '$'; 269 ); 270 271 as_sparc64_gas_info : tasminfo = 272 ( 273 id : as_ggas; 274 idtxt : 'GAS'; 275 asmbin : 'gas'; 276 asmcmd : '$ARCH $PIC -o $OBJ $EXTRAOPT $ASM'; 277 supported_targets : [system_sparc64_linux]; 278 flags : [af_needar,af_smartlink_sections]; 279 labelprefix : '.L'; 280 comment : '# '; 281 dollarsign: '$'; 282 ); 283 284 begin 285 {$ifdef SPARC} 286 RegisterAssembler(as_SPARC_as_info,TGasSPARC); 287 RegisterAssembler(as_SPARC_gas_info,TGasSPARC); 288 {$else SPARC} 289 RegisterAssembler(as_SPARC64_as_info,TGasSPARC); 290 RegisterAssembler(as_SPARC64_gas_info,TGasSPARC); 291 {$endif SPARC} 292 end. 293