summaryrefslogtreecommitdiff
path: root/compiler/sparc/cpugas.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/sparc/cpugas.pas')
-rw-r--r--compiler/sparc/cpugas.pas205
1 files changed, 205 insertions, 0 deletions
diff --git a/compiler/sparc/cpugas.pas b/compiler/sparc/cpugas.pas
new file mode 100644
index 0000000000..9c85857f46
--- /dev/null
+++ b/compiler/sparc/cpugas.pas
@@ -0,0 +1,205 @@
+{
+ Copyright (c) 1999-2003 by Florian Klaempfl
+
+ This unit implements an asmoutput class for SPARC AT&T syntax
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit cpugas;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ cpubase,
+ aasmtai,aasmcpu,assemble,aggas;
+
+ type
+ TGasSPARC=class(TGnuAssembler)
+ procedure WriteInstruction(hp:Tai);override;
+ end;
+
+implementation
+
+ uses
+ cutils,systems,
+ verbose,itcpugas,cgbase,cgutils;
+
+
+ function GetReferenceString(var ref:TReference):string;
+ begin
+ GetReferenceString:='';
+ with ref do
+ begin
+ if (base=NR_NO) and (index=NR_NO) then
+ begin
+ if assigned(symbol) then
+ GetReferenceString:=symbol.name;
+ if offset>0 then
+ GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
+ else if offset<0 then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ case refaddr of
+ addr_hi:
+ GetReferenceString:='%hi('+GetReferenceString+')';
+ addr_lo:
+ GetReferenceString:='%lo('+GetReferenceString+')';
+ end;
+ end
+ else
+ begin
+{$ifdef extdebug}
+ if assigned(symbol) and
+ not(refaddr in [addr_pic,addr_lo]) then
+ internalerror(2003052601);
+{$endif extdebug}
+ if base<>NR_NO then
+ GetReferenceString:=GetReferenceString+gas_regname(base);
+ if index=NR_NO then
+ begin
+ { if (Offset<simm13lo) or (Offset>simm13hi) then
+ internalerror(2003053008); }
+ if offset>0 then
+ GetReferenceString:=GetReferenceString+'+'+ToStr(offset)
+ else if offset<0 then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ {
+ else if (offset=0) and not(assigned(symbol)) then
+ GetReferenceString:=GetReferenceString+ToStr(offset);
+ }
+ if assigned(symbol) then
+ begin
+ if refaddr=addr_lo then
+ GetReferenceString:='%lo('+symbol.name+')+'+GetReferenceString
+ else
+ GetReferenceString:=symbol.name+'+'+GetReferenceString;
+ end;
+ end
+ else
+ begin
+{$ifdef extdebug}
+ if (Offset<>0) or assigned(symbol) then
+ internalerror(2003052603);
+{$endif extdebug}
+ GetReferenceString:=GetReferenceString+'+'+gas_regname(index);
+ end;
+ end;
+ end;
+ end;
+
+
+ function getopstr(const Oper:TOper):string;
+ begin
+ with Oper do
+ case typ of
+ top_reg:
+ getopstr:=gas_regname(reg);
+ top_const:
+ getopstr:=tostr(longint(val));
+ top_ref:
+ if (oper.ref^.refaddr in [addr_no,addr_pic]) or ((oper.ref^.refaddr=addr_lo) and ((oper.ref^.base<>NR_NO) or
+ (oper.ref^.index<>NR_NO))) then
+ getopstr:='['+getreferencestring(ref^)+']'
+ else
+ getopstr:=getreferencestring(ref^);
+ else
+ internalerror(10001);
+ end;
+ end;
+
+
+ procedure TGasSPARC.WriteInstruction(hp:Tai);
+ var
+ Op:TAsmOp;
+ s:String;
+ i:Integer;
+ begin
+ if hp.typ<>ait_instruction then
+ exit;
+ op:=taicpu(hp).opcode;
+ { translate pseudoops, this should be move to a separate pass later, so it's done before
+ peephole optimization }
+ case op of
+ A_FABSd:
+ begin
+ if (taicpu(hp).ops<>2) or
+ (taicpu(hp).oper[0]^.typ<>top_reg) or
+ (taicpu(hp).oper[1]^.typ<>top_reg) then
+ internalerror(200401045);
+ { FABSs %f<even>,%f<even> }
+ s:=#9+std_op2str[A_FABSs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ AsmWriteLn(s);
+ { FMOVs %f<odd>,%f<odd> }
+ inc(taicpu(hp).oper[0]^.reg);
+ inc(taicpu(hp).oper[1]^.reg);
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ dec(taicpu(hp).oper[0]^.reg);
+ dec(taicpu(hp).oper[1]^.reg);
+ AsmWriteLn(s);
+ end;
+ A_FMOVd:
+ begin
+ if (taicpu(hp).ops<>2) or
+ (taicpu(hp).oper[0]^.typ<>top_reg) or
+ (taicpu(hp).oper[1]^.typ<>top_reg) then
+ internalerror(200401045);
+ { FMOVs %f<even>,%f<even> }
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ AsmWriteLn(s);
+ { FMOVs %f<odd>,%f<odd> }
+ inc(taicpu(hp).oper[0]^.reg);
+ inc(taicpu(hp).oper[1]^.reg);
+ s:=#9+std_op2str[A_FMOVs]+#9+getopstr(taicpu(hp).oper[0]^)+','+getopstr(taicpu(hp).oper[1]^);
+ dec(taicpu(hp).oper[0]^.reg);
+ dec(taicpu(hp).oper[1]^.reg);
+ AsmWriteLn(s);
+ end
+ else
+ begin
+ { call maybe not translated to call }
+ s:=#9+std_op2str[op]+cond2str[taicpu(hp).condition];
+ if taicpu(hp).delayslot_annulled then
+ s:=s+',a';
+ if taicpu(hp).ops>0 then
+ begin
+ s:=s+#9+getopstr(taicpu(hp).oper[0]^);
+ for i:=1 to taicpu(hp).ops-1 do
+ s:=s+','+getopstr(taicpu(hp).oper[i]^);
+ end;
+ AsmWriteLn(s);
+ end;
+ end;
+ end;
+
+
+ const
+ as_sparc_as_info : tasminfo =
+ (
+ id : as_gas;
+ idtxt : 'AS';
+ asmbin : 'as';
+ asmcmd : '-o $OBJ $ASM';
+ supported_target : system_any;
+ flags : [af_allowdirect,af_needar,af_smartlink_sections];
+ labelprefix : '.L';
+ comment : '# ';
+ );
+
+begin
+ RegisterAssembler(as_SPARC_as_info,TGasSPARC);
+end.