mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-06 21:07:58 +02:00
* adapted more fpc-mips stuff to trunk
git-svn-id: trunk@14230 -
This commit is contained in:
parent
536529977a
commit
f54365db94
7
.gitattributes
vendored
7
.gitattributes
vendored
@ -244,9 +244,15 @@ compiler/mips/cpuinfo.pas svneol=native#text/plain
|
||||
compiler/mips/cpunode.pas svneol=native#text/plain
|
||||
compiler/mips/cpupara.pas svneol=native#text/plain
|
||||
compiler/mips/cpupi.pas svneol=native#text/plain
|
||||
compiler/mips/cputarg.pas svneol=native#text/pascal
|
||||
compiler/mips/itcpugas.pas svneol=native#text/plain
|
||||
compiler/mips/mipsreg.dat svneol=native#text/plain
|
||||
compiler/mips/ncpuadd.pas svneol=native#text/plain
|
||||
compiler/mips/ncpucall.pas svneol=native#text/pascal
|
||||
compiler/mips/ncpucnv.pas svneol=native#text/pascal
|
||||
compiler/mips/ncpuinln.pas svneol=native#text/pascal
|
||||
compiler/mips/ncpumat.pas svneol=native#text/pascal
|
||||
compiler/mips/ncpuset.pas svneol=native#text/pascal
|
||||
compiler/mips/opcode.inc svneol=native#text/plain
|
||||
compiler/mips/rgcpu.pas svneol=native#text/plain
|
||||
compiler/mips/rmipscon.inc svneol=native#text/plain
|
||||
@ -263,6 +269,7 @@ compiler/mips/rmipssri.inc svneol=native#text/plain
|
||||
compiler/mips/rmipssta.inc svneol=native#text/plain
|
||||
compiler/mips/rmipsstd.inc svneol=native#text/plain
|
||||
compiler/mips/rmipssup.inc svneol=native#text/plain
|
||||
compiler/mips/strinst.inc svneol=native#text/plain
|
||||
compiler/msg/errorct.msg svneol=native#text/plain
|
||||
compiler/msg/errord.msg svneol=native#text/plain
|
||||
compiler/msg/errorda.msg svneol=native#text/plain
|
||||
|
@ -41,13 +41,13 @@ unit agarmgas;
|
||||
procedure WriteExtraHeader; override;
|
||||
end;
|
||||
|
||||
TArmInstrWriter=class(TCPUInstrWriter)
|
||||
TArmInstrWriter=class(TCPUInstrWriter)
|
||||
procedure WriteInstruction(hp : tai);override;
|
||||
end;
|
||||
end;
|
||||
|
||||
TArmAppleGNUAssembler=class(TAppleGNUassembler)
|
||||
constructor create(smart: boolean); override;
|
||||
end;
|
||||
TArmAppleGNUAssembler=class(TAppleGNUassembler)
|
||||
constructor create(smart: boolean); override;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
@ -95,7 +95,7 @@ unit agarmgas;
|
||||
end;
|
||||
|
||||
{****************************************************************************}
|
||||
{ GNU/Apple PPC Assembler writer }
|
||||
{ GNU/Apple ARM Assembler writer }
|
||||
{****************************************************************************}
|
||||
|
||||
constructor TArmAppleGNUAssembler.create(smart: boolean);
|
||||
|
@ -23,224 +23,243 @@ unit cpugas;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
interface
|
||||
|
||||
uses
|
||||
cpubase,
|
||||
aasmtai, aasmcpu, assemble, aggas;
|
||||
uses
|
||||
cpubase,
|
||||
aasmtai, aasmcpu, assemble, aggas;
|
||||
|
||||
type
|
||||
TGasMIPSEL = 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 + ')';
|
||||
type
|
||||
TMIPSGNUAssembler = class(TGNUassembler)
|
||||
constructor create(smart: boolean); override;
|
||||
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
|
||||
|
||||
TMIPSInstrWriter = class(TCPUInstrWriter)
|
||||
procedure WriteInstruction(hp : tai);override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils, systems,
|
||||
verbose, itcpugas, cgbase, cgutils;
|
||||
|
||||
{****************************************************************************}
|
||||
{ GNU MIPS Assembler writer }
|
||||
{****************************************************************************}
|
||||
|
||||
constructor TMIPSGNUAssembler.create(smart: boolean);
|
||||
begin
|
||||
if offset <> 0 then
|
||||
GetReferenceString := ToStr(offset) + GetReferenceString;
|
||||
if assigned(symbol) then
|
||||
inherited create(smart);
|
||||
InstrWriter := TMIPSInstrWriter.create(self);
|
||||
end;
|
||||
|
||||
|
||||
{****************************************************************************}
|
||||
{ Helper routines for Instruction Writer }
|
||||
{****************************************************************************}
|
||||
|
||||
function GetReferenceString(var ref: TReference): string;
|
||||
begin
|
||||
GetReferenceString := '';
|
||||
with ref do
|
||||
begin
|
||||
if refaddr = addr_lo then
|
||||
GetReferenceString := '%lo(' + symbol.Name + ')' + GetReferenceString
|
||||
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_high:
|
||||
GetReferenceString := '%hi(' + GetReferenceString + ')';
|
||||
addr_low:
|
||||
GetReferenceString := '%lo(' + GetReferenceString + ')';
|
||||
end;
|
||||
end
|
||||
else
|
||||
GetReferenceString := symbol.Name + {'+' +} GetReferenceString;
|
||||
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 <> 0 then
|
||||
GetReferenceString := ToStr(offset) + GetReferenceString;
|
||||
if assigned(symbol) then
|
||||
begin
|
||||
if refaddr = addr_low 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
|
||||
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;
|
||||
|
||||
function getopstr_4(const Oper: TOper): string;
|
||||
var
|
||||
tmpref: treference;
|
||||
begin
|
||||
with Oper do
|
||||
case typ of
|
||||
top_ref:
|
||||
function getopstr(const Oper: TOper): string;
|
||||
begin
|
||||
tmpref := ref^;
|
||||
Inc(tmpref.offset, 4);
|
||||
getopstr_4 := getreferencestring(tmpref);
|
||||
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_low) 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;
|
||||
else
|
||||
internalerror(2007050403);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TGasMIPSEL.WriteInstruction(hp: Tai);
|
||||
var
|
||||
Op: TAsmOp;
|
||||
s,s1: string;
|
||||
i: integer;
|
||||
tmpfpu: string;
|
||||
tmpfpu_len: longint;
|
||||
begin
|
||||
if hp.typ <> ait_instruction then
|
||||
exit;
|
||||
op := taicpu(hp).opcode;
|
||||
|
||||
case op of
|
||||
A_P_STK2:
|
||||
begin
|
||||
s1 := getopstr(taicpu(hp).oper[2]^);
|
||||
STK2_LocalSize := align(STK2_LocalSize, 8);
|
||||
if s1[1] = '-' then
|
||||
str(-STK2_LocalSize, s1)
|
||||
else
|
||||
str(STK2_LocalSize, s1);
|
||||
s := #9 + std_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_P_FRAME:
|
||||
begin
|
||||
end;
|
||||
A_P_SET_MACRO:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'macro';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SET_REORDER:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'reorder';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SET_NOMACRO:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'nomacro';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SET_NOREORDER:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'noreorder';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SW:
|
||||
begin
|
||||
s := #9 + std_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_P_LW:
|
||||
begin
|
||||
s := #9 + std_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_LDC1:
|
||||
begin
|
||||
tmpfpu := getopstr(taicpu(hp).oper[0]^);
|
||||
s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
AsmWriteLn(s);
|
||||
|
||||
tmpfpu_len := length(tmpfpu);
|
||||
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
|
||||
s := #9 + std_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
A_SDC1:
|
||||
begin
|
||||
tmpfpu := getopstr(taicpu(hp).oper[0]^);
|
||||
s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
AsmWriteLn(s);
|
||||
|
||||
tmpfpu_len := length(tmpfpu);
|
||||
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
|
||||
s := #9 + std_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
s := #9 + std_op2str[op] + cond2str[taicpu(hp).condition];
|
||||
if taicpu(hp).delayslot_annulled then
|
||||
s := s + ',a';
|
||||
if taicpu(hp).ops > 0 then
|
||||
function getopstr_4(const Oper: TOper): string;
|
||||
var
|
||||
tmpref: treference;
|
||||
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]^);
|
||||
with Oper do
|
||||
case typ of
|
||||
top_ref:
|
||||
begin
|
||||
tmpref := ref^;
|
||||
Inc(tmpref.offset, 4);
|
||||
getopstr_4 := getreferencestring(tmpref);
|
||||
end;
|
||||
else
|
||||
internalerror(2007050403);
|
||||
end;
|
||||
end;
|
||||
AsmWriteLn(s);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
as_MIPSEL_as_info: tasminfo =
|
||||
(
|
||||
id: as_gas;
|
||||
idtxt: 'AS';
|
||||
asmbin: 'as';
|
||||
asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
|
||||
supported_target: system_any;
|
||||
flags: [af_allowdirect, af_needar, af_smartlink_sections];
|
||||
labelprefix: '.L';
|
||||
comment: '# ';
|
||||
);
|
||||
procedure TMIPSInstrWriter.WriteInstruction(hp: Tai);
|
||||
var
|
||||
Op: TAsmOp;
|
||||
s,s1: string;
|
||||
i: integer;
|
||||
tmpfpu: string;
|
||||
tmpfpu_len: longint;
|
||||
begin
|
||||
if hp.typ <> ait_instruction then
|
||||
exit;
|
||||
op := taicpu(hp).opcode;
|
||||
|
||||
case op of
|
||||
A_P_STK2:
|
||||
begin
|
||||
s1 := getopstr(taicpu(hp).oper[2]^);
|
||||
STK2_LocalSize := align(STK2_LocalSize, 8);
|
||||
if s1[1] = '-' then
|
||||
str(-STK2_LocalSize, s1)
|
||||
else
|
||||
str(STK2_LocalSize, s1);
|
||||
s := #9 + gas_op2str[A_ADDIU] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[1]^) + ',' + s1;
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_P_FRAME:
|
||||
begin
|
||||
end;
|
||||
A_P_SET_MACRO:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'macro';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SET_REORDER:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'reorder';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SET_NOMACRO:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'nomacro';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SET_NOREORDER:
|
||||
begin
|
||||
s := #9 + '.set' + #9 + 'noreorder';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_P_SW:
|
||||
begin
|
||||
s := #9 + gas_op2str[A_SW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_P_LW:
|
||||
begin
|
||||
s := #9 + gas_op2str[A_LW] + #9 + getopstr(taicpu(hp).oper[0]^)+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_LDC1:
|
||||
begin
|
||||
tmpfpu := getopstr(taicpu(hp).oper[0]^);
|
||||
s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
owner.AsmWriteLn(s);
|
||||
|
||||
tmpfpu_len := length(tmpfpu);
|
||||
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
|
||||
s := #9 + gas_op2str[A_LWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); // + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
A_SDC1:
|
||||
begin
|
||||
tmpfpu := getopstr(taicpu(hp).oper[0]^);
|
||||
s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
owner.AsmWriteLn(s);
|
||||
|
||||
tmpfpu_len := length(tmpfpu);
|
||||
tmpfpu[tmpfpu_len] := succ(tmpfpu[tmpfpu_len]);
|
||||
s := #9 + gas_op2str[A_SWC1] + #9 + tmpfpu + ',' + getopstr_4(taicpu(hp).oper[1]^); //+ ',' + getopstr(taicpu(hp).oper[2]^) + '(' + getopstr(taicpu(hp).oper[1]^) + ')';
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
s := #9 + gas_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;
|
||||
owner.AsmWriteLn(s);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
as_MIPSEL_as_info: tasminfo =
|
||||
(
|
||||
id: as_gas;
|
||||
idtxt: 'AS';
|
||||
asmbin: 'as';
|
||||
asmcmd: '-mips2 -W -EL -o $OBJ $ASM';
|
||||
supported_targets: [system_mips_linux];
|
||||
flags: [af_allowdirect, af_needar, af_smartlink_sections];
|
||||
labelprefix: '.L';
|
||||
comment: '# ';
|
||||
);
|
||||
|
||||
begin
|
||||
RegisterAssembler(as_MIPSEL_as_info, TGasMIPSEL);
|
||||
RegisterAssembler(as_MIPSEL_as_info, TMIPSGNUAssembler);
|
||||
end.
|
||||
|
57
compiler/mips/cputarg.pas
Normal file
57
compiler/mips/cputarg.pas
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
Copyright (c) 2001 by Peter Vreman
|
||||
|
||||
Includes the i386 dependent target units
|
||||
|
||||
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 cputarg;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
systems { prevent a syntax error when nothing is included }
|
||||
|
||||
{$ifndef NOOPT}
|
||||
,aoptcpu
|
||||
{$endif NOOPT}
|
||||
|
||||
{**************************************
|
||||
Targets
|
||||
**************************************}
|
||||
|
||||
{$ifndef NOTARGETLINUX}
|
||||
,t_linux
|
||||
{$endif}
|
||||
{$ifndef NOTARGETSUNOS}
|
||||
,t_sunos
|
||||
{$endif}
|
||||
|
||||
{**************************************
|
||||
Assemblers
|
||||
**************************************}
|
||||
|
||||
,CpuGas
|
||||
|
||||
;
|
||||
|
||||
end.
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
Copyright (c) 1998-2005 by Florian Klaempfl
|
||||
Copyright (c) 1998-2009 by Mazen NEIFER and David Zhang
|
||||
|
||||
This unit contains the MIPS GAS instruction tables
|
||||
|
||||
@ -25,92 +25,77 @@ unit itcpugas;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
cpubase,cgbase;
|
||||
uses
|
||||
cpubase, cgbase;
|
||||
|
||||
const
|
||||
gas_op2str: array[tasmop] of string[14] = ({$INCLUDE strinst.inc});
|
||||
|
||||
const
|
||||
{ Standard opcode string table (for each tasmop enumeration). The
|
||||
opcode strings should conform to the names as defined by the
|
||||
processor manufacturer.
|
||||
}
|
||||
gas_op2str : op2strtable = (
|
||||
'abs_d','abs_s','add','add_d','add_s','addi','addiu','addu',
|
||||
'and','andi','bc1f','bc1fl','bc1t','bc1tl','bc2f','bc2fl',
|
||||
'bc2t','bc2tl','beq','beql','bgez','bgezal','bgezall','bgezl',
|
||||
'bgtz','bgtzl','blez','blezl','bltz','bltzal','bltzall','bltzl',
|
||||
'bne','bnel','break','c_cond_d','c_cond_s','cache','ceil_w_d','ceil_w_s',
|
||||
'cfc1','cfc2','clo','clz','cop2','ctc1','ctc2','cvt_d_s',
|
||||
'cvt_d_w','cvt_s_d','cvt_s_w','cvt_w_d','cvt_w_s','div','div_d','div_s',
|
||||
'divu','eret','floor_w_d','floor_w_s','j','jal','jalr','jr',
|
||||
'lb','lbu','ldc1','ldc2','lh','lhu','ll','lui',
|
||||
'lw','lwc1','lwc2','lwl','lwr','madd','maddu','mfc0',
|
||||
'mfc1','mfc2','mfhi','mflo','mov_d','mov_s','movf','movf_d',
|
||||
'movf_s','movn','movn_d','movn_s','movt','movt_d','movt_s','movz',
|
||||
'movz_d','movz_s','msub','msubu','mtc0','mtc1','mtc2','mthi',
|
||||
'mtlo','mul','mul_d','mul_s','mult','multu','neg_d','neg_s',
|
||||
'nor','or','ori','pref','round_w_d','round_w_s','sb','sc',
|
||||
'sdc1','sdc2','sh','sll','sllv','slt','slti','sltiu',
|
||||
'sltu','sqrt_d','sqrt_s','sra','srav','srl','srlv','ssnop',
|
||||
'sub','sub_d','sub_s','subu','sw','swc1','swc2','swl',
|
||||
'swr','sync','syscall','teq','teqi','tge','tgei','tgeiu',
|
||||
'tgeu','tlbp','tlbr','tlbwi','tlbwr','tlt','tlti','tltiu',
|
||||
'tltu','tne','tnei','trunc_w_d','trunc_w_s','wait','xor','xori'
|
||||
);
|
||||
|
||||
|
||||
function gas_regnum_search(const s:string):Tregister;
|
||||
function gas_regname(r:Tregister):string;
|
||||
function gas_regnum_search(const s: string): Tregister;
|
||||
function gas_regname(r: Tregister): string;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils,verbose;
|
||||
uses
|
||||
cutils, verbose;
|
||||
|
||||
const
|
||||
gas_regname_table : array[tregisterindex] of string[7] = (
|
||||
{$i rmipsgas.inc}
|
||||
);
|
||||
const
|
||||
gas_regname_table: array[tregisterindex] of string[7] = (
|
||||
{$i rmipsstd.inc}
|
||||
);
|
||||
|
||||
gas_regname_index : array[tregisterindex] of tregisterindex = (
|
||||
gas_regname_index: array[tregisterindex] of tregisterindex = (
|
||||
{$i rmipssri.inc}
|
||||
);
|
||||
|
||||
function findreg_by_gasname(const s:string):tregisterindex;
|
||||
var
|
||||
i,p : tregisterindex;
|
||||
begin
|
||||
{Binary search.}
|
||||
p:=0;
|
||||
i:=regnumber_count_bsstart;
|
||||
repeat
|
||||
if (p+i<=high(tregisterindex)) and (gas_regname_table[gas_regname_index[p+i]]<=s) then
|
||||
p:=p+i;
|
||||
i:=i shr 1;
|
||||
until i=0;
|
||||
if gas_regname_table[gas_regname_index[p]]=s then
|
||||
findreg_by_gasname:=gas_regname_index[p]
|
||||
else
|
||||
findreg_by_gasname:=0;
|
||||
end;
|
||||
);
|
||||
|
||||
|
||||
function gas_regnum_search(const s:string):Tregister;
|
||||
begin
|
||||
result:=regnumber_table[findreg_by_gasname(s)];
|
||||
end;
|
||||
function findreg_by_gasname(const s: string): tregisterindex;
|
||||
var
|
||||
i, p: tregisterindex;
|
||||
begin
|
||||
for p := low(tregisterindex) to high(tregisterindex) do
|
||||
begin
|
||||
if gas_regname_table[gas_regname_index[p]] = s then
|
||||
begin
|
||||
findreg_by_gasname := gas_regname_index[p];
|
||||
exit
|
||||
end;
|
||||
end;
|
||||
findreg_by_gasname := 0;
|
||||
end;
|
||||
|
||||
|
||||
function gas_regname(r:Tregister):string;
|
||||
var
|
||||
p : tregisterindex;
|
||||
begin
|
||||
p:=findreg_by_number(r);
|
||||
if p<>0 then
|
||||
result:=gas_regname_table[p]
|
||||
else
|
||||
result:=generic_regname(r);
|
||||
end;
|
||||
function gas_regnum_search(const s: string): Tregister;
|
||||
begin
|
||||
Result := regnumber_table[findreg_by_gasname(s)];
|
||||
end;
|
||||
|
||||
|
||||
function gas_regname(r: Tregister): string;
|
||||
var
|
||||
hr: tregister;
|
||||
p: longint;
|
||||
begin
|
||||
{ Double uses the same table as single }
|
||||
hr := r;
|
||||
case getsubreg(hr) of
|
||||
R_SUBFD:
|
||||
setsubreg(hr, R_SUBFS);
|
||||
R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
|
||||
setsubreg(hr, R_SUBD);
|
||||
end;
|
||||
p := findreg_by_number(hr);
|
||||
if p <> 0 then
|
||||
Result := gas_regname_table[p]
|
||||
else
|
||||
Result := generic_regname(r);
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log: itcpugas.pas,v $
|
||||
Revision 1.7 2005/02/14 17:13:10 peter
|
||||
* truncate log
|
||||
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ var
|
||||
lfcmp64_L4: tasmlabel;
|
||||
begin
|
||||
|
||||
objectlibrary.getlabel(lfcmp64_L4);
|
||||
current_asmdata.getjumplabel(lfcmp64_L4);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
|
||||
|
||||
@ -155,7 +155,7 @@ var
|
||||
lfcmp64_L4: tasmlabel;
|
||||
begin
|
||||
|
||||
objectlibrary.getlabel(lfcmp64_L4);
|
||||
current_asmdata.getjumplabel(lfcmp64_L4);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 1));
|
||||
|
||||
@ -176,8 +176,8 @@ var
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
|
||||
|
||||
objectlibrary.getlabel(lfcmp64_L4);
|
||||
objectlibrary.getlabel(lfcmp64_L5);
|
||||
current_asmdata.getjumplabel(lfcmp64_L4);
|
||||
current_asmdata.getjumplabel(lfcmp64_L5);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, left_reg.reghi, right_reg.reghi));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
|
||||
@ -203,8 +203,8 @@ var
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
|
||||
|
||||
objectlibrary.getlabel(lfcmp64_L4);
|
||||
objectlibrary.getlabel(lfcmp64_L5);
|
||||
current_asmdata.getjumplabel(lfcmp64_L4);
|
||||
current_asmdata.getjumplabel(lfcmp64_L5);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLT, NR_TCR11, right_reg.reghi, left_reg.reghi));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
|
||||
@ -228,8 +228,8 @@ var
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
|
||||
|
||||
objectlibrary.getlabel(lfcmp64_L4);
|
||||
objectlibrary.getlabel(lfcmp64_L5);
|
||||
current_asmdata.getjumplabel(lfcmp64_L4);
|
||||
current_asmdata.getjumplabel(lfcmp64_L5);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, left_reg.reghi, right_reg.reghi));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L5));
|
||||
@ -255,8 +255,8 @@ var
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI, NR_TCR10, 0));
|
||||
|
||||
objectlibrary.getlabel(lfcmp64_L4);
|
||||
objectlibrary.getlabel(lfcmp64_L5);
|
||||
current_asmdata.getjumplabel(lfcmp64_L4);
|
||||
current_asmdata.getjumplabel(lfcmp64_L5);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SLTU, NR_TCR11, right_reg.reghi, left_reg.reghi));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BNE, NR_TCR11, NR_R0, lfcmp64_L4));
|
||||
@ -422,7 +422,7 @@ begin
|
||||
op := A_C_EQ_D
|
||||
else
|
||||
op := A_C_EQ_S;
|
||||
objectlibrary.getlabel(lfcmpfalse);
|
||||
current_asmdata.getjumplabel(lfcmpfalse);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_OR, location.Register {NR_TCR0}, NR_R0, NR_R0));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse)); //lfcmpfalse
|
||||
@ -437,7 +437,7 @@ begin
|
||||
op := A_C_EQ_D
|
||||
else
|
||||
op := A_C_EQ_S;
|
||||
objectlibrary.getlabel(lfcmpfalse);
|
||||
current_asmdata.getjumplabel(lfcmpfalse);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1F, lfcmpfalse));
|
||||
@ -451,7 +451,7 @@ begin
|
||||
op := A_C_LT_D
|
||||
else
|
||||
op := A_C_LT_S;
|
||||
objectlibrary.getlabel(lfcmptrue);
|
||||
current_asmdata.getjumplabel(lfcmptrue);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
|
||||
@ -465,7 +465,7 @@ begin
|
||||
op := A_C_LE_D
|
||||
else
|
||||
op := A_C_LE_S;
|
||||
objectlibrary.getlabel(lfcmptrue);
|
||||
current_asmdata.getjumplabel(lfcmptrue);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, left.location.Register, right.location.Register));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
|
||||
@ -479,7 +479,7 @@ begin
|
||||
op := A_C_LT_D
|
||||
else
|
||||
op := A_C_LT_S;
|
||||
objectlibrary.getlabel(lfcmptrue);
|
||||
current_asmdata.getjumplabel(lfcmptrue);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
|
||||
@ -493,7 +493,7 @@ begin
|
||||
op := A_C_LE_D
|
||||
else
|
||||
op := A_C_LE_S;
|
||||
objectlibrary.getlabel(lfcmptrue);
|
||||
current_asmdata.getjumplabel(lfcmptrue);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ORI, location.Register{NR_TCR0}, NR_R0, 1));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, right.location.Register, left.location.Register));
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_sym(A_BC1T, lfcmptrue));
|
||||
|
62
compiler/mips/ncpucall.pas
Normal file
62
compiler/mips/ncpucall.pas
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
|
||||
|
||||
Generate MIPSEL assembler for in call nodes
|
||||
|
||||
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 ncpucall;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ncgcal;
|
||||
|
||||
type
|
||||
tMIPSELcallnode = class(tcgcallnode)
|
||||
procedure extra_call_code; override;
|
||||
procedure extra_post_call_code; override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
cpubase,
|
||||
aasmtai,aasmcpu,aasmdata,
|
||||
paramgr,
|
||||
ncal;
|
||||
|
||||
procedure tMIPSELcallnode.extra_call_code;
|
||||
begin
|
||||
if pushedparasize > 0 then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, -pushedparasize));
|
||||
end;
|
||||
|
||||
procedure tMIPSELcallnode.extra_post_call_code;
|
||||
begin
|
||||
if pushedparasize > 0 then
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_ADDIU, NR_STACK_POINTER_REG, NR_STACK_POINTER_REG, pushedparasize));
|
||||
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
ccallnode := TMIPSELCallNode;
|
||||
end.
|
285
compiler/mips/ncpucnv.pas
Normal file
285
compiler/mips/ncpucnv.pas
Normal file
@ -0,0 +1,285 @@
|
||||
{
|
||||
Copyright (c) 1998-2002 by Florian Klaempfl and David Zhang
|
||||
|
||||
Generate MIPSEL assembler for type converting nodes
|
||||
|
||||
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 ncpucnv;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
node, ncnv, ncgcnv, defcmp;
|
||||
|
||||
type
|
||||
tMIPSELtypeconvnode = class(TCgTypeConvNode)
|
||||
protected
|
||||
{ procedure second_int_to_int;override; }
|
||||
{ procedure second_string_to_string;override; }
|
||||
{ procedure second_cstring_to_pchar;override; }
|
||||
{ procedure second_string_to_chararray;override; }
|
||||
{ procedure second_array_to_pointer;override; }
|
||||
function first_int_to_real: tnode; override;
|
||||
{ procedure second_pointer_to_array;override; }
|
||||
{ procedure second_chararray_to_string;override; }
|
||||
{ procedure second_char_to_string;override; }
|
||||
procedure second_int_to_real; override;
|
||||
procedure second_real_to_real; override;
|
||||
{ procedure second_cord_to_pointer;override; }
|
||||
{ procedure second_proc_to_procvar;override; }
|
||||
{ procedure second_bool_to_int;override; }
|
||||
procedure second_int_to_bool; override;
|
||||
{ procedure second_load_smallset;override; }
|
||||
{ procedure second_ansistring_to_pchar;override; }
|
||||
{ procedure second_pchar_to_string;override; }
|
||||
{ procedure second_class_to_intf;override; }
|
||||
{ procedure second_char_to_char;override; }
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose, globtype, globals, systems,
|
||||
symconst, symdef, aasmbase, aasmtai, aasmdata,
|
||||
defutil,
|
||||
cgbase, cgutils, pass_1, pass_2, procinfo,
|
||||
ncon, ncal,
|
||||
ncgutil,
|
||||
cpubase, aasmcpu,
|
||||
tgobj, cgobj;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
FirstTypeConv
|
||||
*****************************************************************************}
|
||||
|
||||
function tMIPSELtypeconvnode.first_int_to_real: tnode;
|
||||
var
|
||||
fname: string[19];
|
||||
begin
|
||||
{ converting a 64bit integer to a float requires a helper }
|
||||
if is_64bitint(left.resultdef) or
|
||||
is_currency(left.resultdef) then
|
||||
begin
|
||||
{ hack to avoid double division by 10000, as it's
|
||||
already done by resulttypepass.resulttype_int_to_real }
|
||||
if is_currency(left.resultdef) then
|
||||
left.resultdef := s64inttype;
|
||||
if is_signed(left.resultdef) then
|
||||
fname := 'fpc_int64_to_double'
|
||||
else
|
||||
fname := 'fpc_qword_to_double';
|
||||
Result := ccallnode.createintern(fname, ccallparanode.Create(
|
||||
left, nil));
|
||||
left := nil;
|
||||
firstpass(Result);
|
||||
exit;
|
||||
end
|
||||
else
|
||||
{ other integers are supposed to be 32 bit }
|
||||
begin
|
||||
if is_signed(left.resultdef) then
|
||||
inserttypeconv(left, s32inttype)
|
||||
else
|
||||
inserttypeconv(left, u32inttype);
|
||||
firstpass(left);
|
||||
end;
|
||||
Result := nil;
|
||||
expectloc := LOC_FPUREGISTER;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
SecondTypeConv
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tMIPSELtypeconvnode.second_int_to_real;
|
||||
|
||||
procedure loadsigned;
|
||||
begin
|
||||
location_force_mem(current_asmdata.CurrAsmList, left.location);
|
||||
location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
|
||||
{ Load memory in fpu register }
|
||||
cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F32, OS_F32, left.location.reference, location.Register);
|
||||
tg.ungetiftemp(current_asmdata.CurrAsmList, left.location.reference);
|
||||
{ Convert value in fpu register from integer to float }
|
||||
case tfloatdef(resultdef).floattype of
|
||||
s32real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_S_W, location.Register, location.Register));
|
||||
s64real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_D_W, location.Register, location.Register));
|
||||
else
|
||||
internalerror(200408011);
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
href: treference;
|
||||
hregister: tregister;
|
||||
l1, l2: tasmlabel;
|
||||
|
||||
begin
|
||||
location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
|
||||
if is_signed(left.resultdef) then
|
||||
loadsigned
|
||||
else
|
||||
begin
|
||||
current_asmdata.getdatalabel(l1);
|
||||
current_asmdata.getjumplabel(l2);
|
||||
reference_reset_symbol(href, l1, 0, sizeof(aint));
|
||||
hregister := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
|
||||
cg.a_load_loc_reg(current_asmdata.CurrAsmList, OS_32, left.location, hregister);
|
||||
|
||||
loadsigned;
|
||||
|
||||
current_asmdata.CurrAsmList.concat(Taicpu.op_reg_reg_sym(A_BGE, hregister, NR_R0, l2));
|
||||
|
||||
case tfloatdef(resultdef).floattype of
|
||||
{ converting dword to s64real first and cut off at the end avoids precision loss }
|
||||
s32real,
|
||||
s64real:
|
||||
begin
|
||||
hregister := cg.getfpuregister(current_asmdata.CurrAsmList, OS_F64);
|
||||
current_asmdata.asmlists[al_typedconsts].concat(tai_align.Create(const_align(8)));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
|
||||
|
||||
{ I got this constant from a test program (FK) }
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($0000f041));
|
||||
|
||||
cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, OS_F64, OS_F64, href, hregister);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_ADD_D, location.Register, hregister, location.Register));
|
||||
cg.a_label(current_asmdata.CurrAsmList, l2);
|
||||
|
||||
{ cut off if we should convert to single }
|
||||
if tfloatdef(resultdef).floattype = s32real then
|
||||
begin
|
||||
hregister := location.Register;
|
||||
location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_CVT_S_D, location.Register, hregister));
|
||||
end;
|
||||
end;
|
||||
else
|
||||
internalerror(200410031);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELtypeconvnode.second_real_to_real;
|
||||
const
|
||||
conv_op: array[tfloattype, tfloattype] of tasmop = (
|
||||
{ from: s32 s64 s80 c64 cur f128 }
|
||||
{ s32 } (A_MOV_S, A_CVT_S_D, A_NONE, A_NONE, A_NONE, A_NONE),
|
||||
{ s64 } (A_CVT_D_S, A_MOV_D, A_NONE, A_NONE, A_NONE, A_NONE),
|
||||
{ s80 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
|
||||
{ c64 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
|
||||
{ cur } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE),
|
||||
{ f128 } (A_NONE, A_NONE, A_NONE, A_NONE, A_NONE, A_NONE)
|
||||
);
|
||||
var
|
||||
op: tasmop;
|
||||
begin
|
||||
location_reset(location, LOC_FPUREGISTER, def_cgsize(resultdef));
|
||||
location_force_fpureg(current_asmdata.CurrAsmList, left.location, False);
|
||||
{ Convert value in fpu register from integer to float }
|
||||
op := conv_op[tfloatdef(resultdef).floattype, tfloatdef(left.resultdef).floattype];
|
||||
if op = A_NONE then
|
||||
internalerror(200401121);
|
||||
location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op, location.Register, left.location.Register));
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELtypeconvnode.second_int_to_bool;
|
||||
var
|
||||
hreg1, hreg2: tregister;
|
||||
opsize: tcgsize;
|
||||
hlabel, oldtruelabel, oldfalselabel: tasmlabel;
|
||||
begin
|
||||
oldtruelabel := current_procinfo.CurrTrueLabel;
|
||||
oldfalselabel := current_procinfo.CurrFalseLabel;
|
||||
current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
|
||||
current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
|
||||
secondpass(left);
|
||||
if codegenerror then
|
||||
exit;
|
||||
|
||||
{ byte(boolean) or word(wordbool) or longint(longbool) must }
|
||||
{ be accepted for var parameters }
|
||||
if (nf_explicit in flags) and
|
||||
(left.resultdef.size = resultdef.size) and
|
||||
(left.location.loc in [LOC_REFERENCE, LOC_CREFERENCE, LOC_CREGISTER]) then
|
||||
begin
|
||||
location_copy(location, left.location);
|
||||
current_procinfo.CurrTrueLabel := oldtruelabel;
|
||||
current_procinfo.CurrFalseLabel := oldfalselabel;
|
||||
exit;
|
||||
end;
|
||||
location_reset(location, LOC_REGISTER, def_cgsize(resultdef));
|
||||
opsize := def_cgsize(left.resultdef);
|
||||
case left.location.loc of
|
||||
LOC_CREFERENCE, LOC_REFERENCE, LOC_REGISTER, LOC_CREGISTER:
|
||||
begin
|
||||
if left.location.loc in [LOC_CREFERENCE, LOC_REFERENCE] then
|
||||
begin
|
||||
hreg2 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList, opsize, opsize, left.location.reference, hreg2);
|
||||
end
|
||||
else
|
||||
hreg2 := left.location.Register;
|
||||
{$ifndef cpu64bit}
|
||||
if left.location.size in [OS_64, OS_S64] then
|
||||
begin
|
||||
hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
|
||||
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hreg2, tregister(succ(longint(hreg2))), hreg1);
|
||||
hreg2 := hreg1;
|
||||
opsize := OS_32;
|
||||
end;
|
||||
{$endif cpu64bit}
|
||||
hreg1 := cg.getintregister(current_asmdata.CurrAsmList, opsize);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SNE, hreg1, hreg2, NR_R0));
|
||||
end;
|
||||
LOC_JUMP:
|
||||
begin
|
||||
hreg1 := cg.getintregister(current_asmdata.CurrAsmList, OS_INT);
|
||||
current_asmdata.getjumplabel(hlabel);
|
||||
cg.a_label(current_asmdata.CurrAsmList, current_procinfo.CurrTrueLabel);
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 1, hreg1);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList, hlabel);
|
||||
cg.a_label(current_asmdata.CurrAsmList, current_procinfo.CurrFalseLabel);
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_INT, 0, hreg1);
|
||||
cg.a_label(current_asmdata.CurrAsmList, hlabel);
|
||||
end;
|
||||
else
|
||||
internalerror(10062);
|
||||
end;
|
||||
location.Register := hreg1;
|
||||
|
||||
if location.size in [OS_64, OS_S64] then
|
||||
internalerror(200408241);
|
||||
|
||||
current_procinfo.CurrTrueLabel := oldtruelabel;
|
||||
current_procinfo.CurrFalseLabel := oldfalselabel;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
ctypeconvnode := tMIPSELtypeconvnode;
|
||||
end.
|
138
compiler/mips/ncpuinln.pas
Normal file
138
compiler/mips/ncpuinln.pas
Normal file
@ -0,0 +1,138 @@
|
||||
{
|
||||
Copyright (c) 1998-2009 by Florian Klaempfl and David Zhang
|
||||
|
||||
Generate MIPSEL inline nodes
|
||||
|
||||
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 ncpuinln;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
node, ninl, ncginl;
|
||||
|
||||
type
|
||||
tMIPSELinlinenode = class(tcgInlineNode)
|
||||
function first_abs_real: tnode; override;
|
||||
function first_sqr_real: tnode; override;
|
||||
function first_sqrt_real: tnode; override;
|
||||
procedure second_abs_real; override;
|
||||
procedure second_sqr_real; override;
|
||||
procedure second_sqrt_real; override;
|
||||
private
|
||||
procedure load_fpu_location;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
systems,
|
||||
globtype,
|
||||
cutils, verbose,
|
||||
symconst, symdef,
|
||||
aasmtai, aasmcpu, aasmdata,
|
||||
cgbase, pass_2,
|
||||
cpubase, paramgr,
|
||||
nbas, ncon, ncal, ncnv, nld,
|
||||
ncgutil, cgobj, cgutils;
|
||||
|
||||
{*****************************************************************************
|
||||
tMIPSELinlinenode
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tMIPSELinlinenode.load_fpu_location;
|
||||
begin
|
||||
secondpass(left);
|
||||
location_force_fpureg(current_asmdata.CurrAsmList, left.location, True);
|
||||
location_copy(location, left.location);
|
||||
if left.location.loc = LOC_CFPUREGISTER then
|
||||
begin
|
||||
location.Register := cg.getfpuregister(current_asmdata.CurrAsmList, location.size);
|
||||
location.loc := LOC_FPUREGISTER;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function tMIPSELinlinenode.first_abs_real: tnode;
|
||||
begin
|
||||
expectloc := LOC_FPUREGISTER;
|
||||
first_abs_real := nil;
|
||||
end;
|
||||
|
||||
|
||||
function tMIPSELinlinenode.first_sqr_real: tnode;
|
||||
begin
|
||||
expectloc := LOC_FPUREGISTER;
|
||||
first_sqr_real := nil;
|
||||
end;
|
||||
|
||||
|
||||
function tMIPSELinlinenode.first_sqrt_real: tnode;
|
||||
begin
|
||||
expectloc := LOC_FPUREGISTER;
|
||||
first_sqrt_real := nil;
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELinlinenode.second_abs_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
case tfloatdef(left.resultdef).floattype of
|
||||
s32real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ABS_s, location.Register, left.location.Register));
|
||||
s64real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_ABS_d, location.Register, left.location.Register));
|
||||
else
|
||||
internalerror(200410031);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELinlinenode.second_sqr_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
case tfloatdef(left.resultdef).floattype of
|
||||
s32real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MUL_s, location.Register, left.location.Register, left.location.Register));
|
||||
s64real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_MUL_d, location.Register, left.location.Register, left.location.Register));
|
||||
else
|
||||
internalerror(200410032);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELinlinenode.second_sqrt_real;
|
||||
begin
|
||||
load_fpu_location;
|
||||
case tfloatdef(left.resultdef).floattype of
|
||||
s32real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRT_s, location.Register, left.location.Register));
|
||||
s64real:
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_SQRT_d, location.Register, left.location.Register));
|
||||
else
|
||||
internalerror(200410033);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
cInlineNode := tMIPSELinlinenode;
|
||||
end.
|
302
compiler/mips/ncpumat.pas
Normal file
302
compiler/mips/ncpumat.pas
Normal file
@ -0,0 +1,302 @@
|
||||
{
|
||||
David Zhang 2007/01/15
|
||||
$Id: ncpumat.pas,v 1.23 2005/02/14 17:13:10 peter Exp $
|
||||
Copyright (c) 1998-2002 by Florian Klaempfl
|
||||
|
||||
Generate MIPSel assembler for math nodes
|
||||
|
||||
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 ncpumat;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
node, nmat, ncgmat;
|
||||
|
||||
type
|
||||
tMIPSELmoddivnode = class(tmoddivnode)
|
||||
procedure pass_generate_code;override;
|
||||
end;
|
||||
|
||||
tMIPSELshlshrnode = class(tshlshrnode)
|
||||
procedure pass_generate_code;override;
|
||||
{ everything will be handled in pass_2 }
|
||||
function first_shlshr64bitint: tnode; override;
|
||||
end;
|
||||
|
||||
tMIPSELnotnode = class(tcgnotnode)
|
||||
procedure second_boolean; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype, systems,
|
||||
cutils, verbose, globals,
|
||||
symconst,
|
||||
aasmbase, aasmcpu, aasmtai, aasmdata,
|
||||
defutil,
|
||||
procinfo,
|
||||
cgbase, cgobj, pass_2,
|
||||
ncon,
|
||||
cpubase,
|
||||
ncgutil, cgcpu, cgutils;
|
||||
|
||||
{*****************************************************************************
|
||||
TMipselMODDIVNODE
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tMIPSELmoddivnode.pass_generate_code;
|
||||
var
|
||||
power: longint;
|
||||
tmpreg, numerator, divider, resultreg: tregister;
|
||||
begin
|
||||
secondpass(left);
|
||||
secondpass(right);
|
||||
location_copy(location, left.location);
|
||||
|
||||
{ put numerator in register }
|
||||
location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
|
||||
location_copy(location, left.location);
|
||||
numerator := location.Register;
|
||||
|
||||
if (nodetype = modn) then
|
||||
resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT)
|
||||
else
|
||||
begin
|
||||
if (location.loc = LOC_CREGISTER) then
|
||||
begin
|
||||
location.loc := LOC_REGISTER;
|
||||
location.Register := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
|
||||
end;
|
||||
resultreg := location.Register;
|
||||
end;
|
||||
|
||||
if (nodetype = divn) and
|
||||
(right.nodetype = ordconstn) and
|
||||
ispowerof2(tordconstnode(right).Value.svalue, power) then
|
||||
begin
|
||||
tmpreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, 31, numerator, tmpreg);
|
||||
{ if signed, tmpreg=right value-1, otherwise 0 }
|
||||
cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_AND, OS_INT, tordconstnode(right).Value.svalue - 1, tmpreg);
|
||||
{ add to the left value }
|
||||
cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_ADD, OS_INT, tmpreg, numerator);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SAR, OS_INT, aword(power), numerator, resultreg);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ load divider in a register if necessary }
|
||||
location_force_reg(current_asmdata.CurrAsmList, right.location,
|
||||
def_cgsize(right.resultdef), True);
|
||||
divider := right.location.Register;
|
||||
|
||||
|
||||
if (nodetype = modn) then
|
||||
begin
|
||||
if is_signed(right.resultdef) then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_REM, resultreg, numerator, divider));
|
||||
end
|
||||
else
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_REMU, resultreg, numerator, divider));
|
||||
end
|
||||
else
|
||||
begin
|
||||
if is_signed({left.resultdef}right.resultdef) then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIV, resultreg, numerator, divider));
|
||||
end
|
||||
else
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_DIVU, resultreg, numerator, divider));
|
||||
end;
|
||||
end;
|
||||
{ set result location }
|
||||
location.loc := LOC_REGISTER;
|
||||
location.Register := resultreg;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TMIPSelSHLRSHRNODE
|
||||
*****************************************************************************}
|
||||
|
||||
function TMIPSELShlShrNode.first_shlshr64bitint: TNode;
|
||||
begin
|
||||
{ 64bit without constants need a helper }
|
||||
if is_64bit(left.resultdef) and
|
||||
(right.nodetype <> ordconstn) then
|
||||
begin
|
||||
Result := inherited first_shlshr64bitint;
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
|
||||
procedure tMIPSELshlshrnode.pass_generate_code;
|
||||
var
|
||||
hregister, resultreg, hregister1, hreg64hi, hreg64lo: tregister;
|
||||
op: topcg;
|
||||
shiftval: aword;
|
||||
begin
|
||||
{ 64bit without constants need a helper, and is
|
||||
already replaced in pass1 }
|
||||
if is_64bit(left.resultdef) and
|
||||
(right.nodetype <> ordconstn) then
|
||||
internalerror(200405301);
|
||||
|
||||
secondpass(left);
|
||||
secondpass(right);
|
||||
if is_64bit(left.resultdef) then
|
||||
begin
|
||||
location_reset(location, LOC_REGISTER, OS_64);
|
||||
|
||||
{ load left operator in a register }
|
||||
location_force_reg(current_asmdata.CurrAsmList, left.location, OS_64, False);
|
||||
|
||||
|
||||
hreg64hi := left.location.register64.reghi;
|
||||
hreg64lo := left.location.register64.reglo;
|
||||
|
||||
shiftval := tordconstnode(right).Value.svalue and 63;
|
||||
if shiftval > 31 then
|
||||
begin
|
||||
if nodetype = shln then
|
||||
begin
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_32, 0, hreg64hi);
|
||||
if (shiftval and 31) <> 0 then
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval and 31, hreg64lo, hreg64lo);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList, OS_32, 0, hreg64lo);
|
||||
if (shiftval and 31) <> 0 then
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval and 31, hreg64hi, hreg64hi);
|
||||
end;
|
||||
location.register64.reglo := hreg64hi;
|
||||
location.register64.reghi := hreg64lo;
|
||||
end
|
||||
else
|
||||
begin
|
||||
hregister := cg.getintregister(current_asmdata.CurrAsmList, OS_32);
|
||||
if nodetype = shln then
|
||||
begin
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, 32 - shiftval, hreg64lo, hregister);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval, hreg64hi, hreg64hi);
|
||||
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hregister, hreg64hi, hreg64hi);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, shiftval, hreg64lo, hreg64lo);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_32, 32 - shiftval, hreg64hi, hregister);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval, hreg64lo, hreg64lo);
|
||||
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, OP_OR, OS_32, hregister, hreg64lo, hreg64lo);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, OS_32, shiftval, hreg64hi, hreg64hi);
|
||||
end;
|
||||
location.register64.reghi := hreg64hi;
|
||||
location.register64.reglo := hreg64lo;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ load left operators in a register }
|
||||
location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
|
||||
location_copy(location, left.location);
|
||||
resultreg := location.Register;
|
||||
hregister1 := location.Register;
|
||||
if (location.loc = LOC_CREGISTER) then
|
||||
begin
|
||||
location.loc := LOC_REGISTER;
|
||||
resultreg := cg.GetIntRegister(current_asmdata.CurrAsmList, OS_INT);
|
||||
location.Register := resultreg;
|
||||
end;
|
||||
{ determine operator }
|
||||
if nodetype = shln then
|
||||
op := OP_SHL
|
||||
else
|
||||
op := OP_SHR;
|
||||
{ shifting by a constant directly coded: }
|
||||
if (right.nodetype = ordconstn) then
|
||||
begin
|
||||
if tordconstnode(right).Value.svalue and 31 <> 0 then
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, op, OS_32, tordconstnode(right).Value.svalue and 31, hregister1, resultreg);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ load shift count in a register if necessary }
|
||||
location_force_reg(current_asmdata.CurrAsmList, right.location, def_cgsize(right.resultdef), True);
|
||||
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList, op, OS_32, right.location.Register, hregister1, resultreg);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TMIPSelNOTNODE
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tMIPSELnotnode.second_boolean;
|
||||
var
|
||||
hl: tasmlabel;
|
||||
begin
|
||||
{ if the location is LOC_JUMP, we do the secondpass after the
|
||||
labels are allocated
|
||||
}
|
||||
if left.expectloc = LOC_JUMP then
|
||||
begin
|
||||
hl := current_procinfo.CurrTrueLabel;
|
||||
current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
|
||||
current_procinfo.CurrFalseLabel := hl;
|
||||
secondpass(left);
|
||||
maketojumpbool(current_asmdata.CurrAsmList, left, lr_load_regvars);
|
||||
hl := current_procinfo.CurrTrueLabel;
|
||||
current_procinfo.CurrTrueLabel := current_procinfo.CurrFalseLabel;
|
||||
current_procinfo.CurrFalseLabel := hl;
|
||||
location.loc := LOC_JUMP;
|
||||
end
|
||||
else
|
||||
begin
|
||||
secondpass(left);
|
||||
case left.location.loc of
|
||||
LOC_FLAGS:
|
||||
begin
|
||||
internalerror(2007011501);
|
||||
end;
|
||||
LOC_REGISTER, LOC_CREGISTER, LOC_REFERENCE, LOC_CREFERENCE:
|
||||
begin
|
||||
location_force_reg(current_asmdata.CurrAsmList, left.location, def_cgsize(left.resultdef), True);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_SEQ, NR_TCR0, left.location.Register, NR_R0));
|
||||
location_reset(location, LOC_REGISTER, OS_INT);
|
||||
location.Register := NR_TCR0;
|
||||
end;
|
||||
else
|
||||
internalerror(2003042401);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
cmoddivnode := tMIPSELmoddivnode;
|
||||
cshlshrnode := tMIPSELshlshrnode;
|
||||
cnotnode := tMIPSELnotnode;
|
||||
end.
|
130
compiler/mips/ncpuset.pas
Normal file
130
compiler/mips/ncpuset.pas
Normal file
@ -0,0 +1,130 @@
|
||||
{
|
||||
Copyright (c) 1998-2004 by Florian Klaempfl and David Zhang
|
||||
|
||||
Generate MIPSEL assembler for in set/case nodes
|
||||
|
||||
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 ncpuset;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
globtype,
|
||||
nset,
|
||||
ncgset;
|
||||
|
||||
type
|
||||
tcpucasenode = class(tcgcasenode)
|
||||
protected
|
||||
procedure optimizevalues(var max_linear_list: aint; var max_dist: aword); override;
|
||||
function has_jumptable: boolean; override;
|
||||
procedure genjumptable(hp: pcaselabel; min_, max_: aint); override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globals,
|
||||
systems,
|
||||
constexp,
|
||||
cpubase,
|
||||
aasmbase, aasmtai, aasmcpu, aasmdata,
|
||||
cgbase, cgutils, cgobj,
|
||||
procinfo;
|
||||
|
||||
procedure tcpucasenode.optimizevalues(var max_linear_list: aint; var max_dist: aword);
|
||||
begin
|
||||
{ give the jump table a higher priority }
|
||||
max_dist := (max_dist * 3) div 2;
|
||||
end;
|
||||
|
||||
|
||||
function tcpucasenode.has_jumptable: boolean;
|
||||
begin
|
||||
has_jumptable := True;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcpucasenode.genjumptable(hp: pcaselabel; min_, max_: aint);
|
||||
var
|
||||
table: tasmlabel;
|
||||
last: TConstExprInt;
|
||||
indexreg, jmpreg, basereg: tregister;
|
||||
href: treference;
|
||||
jumpsegment: TAsmlist;
|
||||
|
||||
procedure genitem(t: pcaselabel);
|
||||
var
|
||||
i: aint;
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(t^.less);
|
||||
{ fill possible hole }
|
||||
for i := last.svalue+1 to t^._low.svalue-1 do
|
||||
jumpSegment.concat(Tai_const.Create_sym(elselabel));
|
||||
for i := t^._low.svalue to t^._high.svalue do
|
||||
jumpSegment.concat(Tai_const.Create_sym(blocklabel(t^.blockid)));
|
||||
last := t^._high;
|
||||
if assigned(t^.greater) then
|
||||
genitem(t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
jumpsegment := current_procinfo.aktlocaldata;
|
||||
if not (jumptable_no_range) then
|
||||
begin
|
||||
{ case expr less than min_ => goto elselabel }
|
||||
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_lt, aint(min_), hregister, elselabel);
|
||||
{ case expr greater than max_ => goto elselabel }
|
||||
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, jmp_gt, aint(max_), hregister, elselabel);
|
||||
end;
|
||||
current_asmdata.getjumplabel(table);
|
||||
indexreg := cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHL, OS_ADDR, 2, hregister, indexreg);
|
||||
{ create reference }
|
||||
reference_reset_symbol(href, table, 0, sizeof(aint));
|
||||
href.offset := (-aint(min_)) * 4;
|
||||
basereg := cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList, href, basereg);
|
||||
|
||||
jmpreg := cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
|
||||
reference_reset(href, sizeof(aint));
|
||||
href.index := indexreg;
|
||||
href.base := basereg;
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList, OS_ADDR, OS_ADDR, href, jmpreg);
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_JR, jmpreg));
|
||||
{ Delay slot }
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_NOP));
|
||||
{ generate jump table }
|
||||
if not(cs_opt_size in current_settings.optimizerswitches) then
|
||||
jumpSegment.concat(Tai_Align.Create_Op(4, 0));
|
||||
jumpSegment.concat(Tai_label.Create(table));
|
||||
last := min_;
|
||||
genitem(hp);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
ccasenode := tcpucasenode;
|
||||
end.
|
241
compiler/mips/strinst.inc
Normal file
241
compiler/mips/strinst.inc
Normal file
@ -0,0 +1,241 @@
|
||||
'none',
|
||||
'p_stk2',
|
||||
'p_lw',
|
||||
'p_set_noreorder',
|
||||
'p_set_nomacro',
|
||||
'p_set_macro',
|
||||
'p_set_reorder',
|
||||
'p_frame',
|
||||
'p_mask',
|
||||
'p_fmask',
|
||||
'p_sw',
|
||||
'sparc8unimp',
|
||||
'nop',
|
||||
'not',
|
||||
'neg',
|
||||
'negu',
|
||||
'b',
|
||||
'li',
|
||||
'dli',
|
||||
'la',
|
||||
'move',
|
||||
'lb',
|
||||
'lbu',
|
||||
'lh',
|
||||
'lhu',
|
||||
'lw',
|
||||
'lwu',
|
||||
'lwl',
|
||||
'lwr',
|
||||
'ld',
|
||||
'ldl',
|
||||
'ldr',
|
||||
'll',
|
||||
'lld',
|
||||
'sb',
|
||||
'sh',
|
||||
'sw',
|
||||
'swl',
|
||||
'swr',
|
||||
'sd',
|
||||
'sdl',
|
||||
'sdr',
|
||||
'sc',
|
||||
'scd',
|
||||
'sync',
|
||||
'addi',
|
||||
'daddi',
|
||||
'addiu',
|
||||
'daddiu',
|
||||
'slti',
|
||||
'sltiu',
|
||||
'andi',
|
||||
'ori',
|
||||
'xori',
|
||||
'lui',
|
||||
'dneg',
|
||||
'dnegu',
|
||||
'add',
|
||||
'dadd',
|
||||
'addu',
|
||||
'daddu',
|
||||
'sub',
|
||||
'dsub',
|
||||
'subu',
|
||||
'dsubu',
|
||||
'slt',
|
||||
'sltu',
|
||||
'and',
|
||||
'or',
|
||||
'xor',
|
||||
'nor',
|
||||
'mul',
|
||||
'mulo',
|
||||
'mulou',
|
||||
'dmul',
|
||||
'dmulo',
|
||||
'dmulou',
|
||||
'div',
|
||||
'divu',
|
||||
'ddiv',
|
||||
'ddivu',
|
||||
'rem',
|
||||
'remu',
|
||||
'drem',
|
||||
'dremu',
|
||||
'mult',
|
||||
'dmult',
|
||||
'multu',
|
||||
'dmultu',
|
||||
'mfhi',
|
||||
'mthi',
|
||||
'mflo',
|
||||
'mtlo',
|
||||
'multg',
|
||||
'dmultg',
|
||||
'multug',
|
||||
'dmultug',
|
||||
'divg',
|
||||
'ddivg',
|
||||
'divug',
|
||||
'ddivug',
|
||||
'modg',
|
||||
'dmodg',
|
||||
'modug',
|
||||
'dmodug',
|
||||
'j',
|
||||
'jal',
|
||||
'jr',
|
||||
'jalr',
|
||||
'beq',
|
||||
'bne',
|
||||
'blez',
|
||||
'bgtz',
|
||||
'bltz',
|
||||
'bgez',
|
||||
'bltzal',
|
||||
'bgezal',
|
||||
'beql',
|
||||
'bnel',
|
||||
'blezl',
|
||||
'bgtzl',
|
||||
'bltzl',
|
||||
'bgezl',
|
||||
'bltzall',
|
||||
'bgezall',
|
||||
'sll',
|
||||
'srl',
|
||||
'sra',
|
||||
'sllv',
|
||||
'srlv',
|
||||
'srav',
|
||||
'dsll',
|
||||
'dsrl',
|
||||
'dsra',
|
||||
'dsllv',
|
||||
'dsrlv',
|
||||
'dsrav',
|
||||
'dsll32',
|
||||
'dsrl32',
|
||||
'dsra32',
|
||||
'lwc1',
|
||||
'swc1',
|
||||
'ldc1',
|
||||
'sdc1',
|
||||
'mtc1',
|
||||
'mfc1',
|
||||
'dmtc1',
|
||||
'dmfc1',
|
||||
'ctc1',
|
||||
'cfc1',
|
||||
'add.s',
|
||||
'add.d',
|
||||
'sub.s',
|
||||
'sub.d',
|
||||
'mul.s',
|
||||
'mul.d',
|
||||
'div.s',
|
||||
'div.d',
|
||||
'abs.s',
|
||||
'abs.d',
|
||||
'neg.s',
|
||||
'neg.d',
|
||||
'sqrt.s',
|
||||
'sqrt.d',
|
||||
'mov.s',
|
||||
'mov.d',
|
||||
'cvt.s.d',
|
||||
'cvt.s.w',
|
||||
'cvt.s.l',
|
||||
'cvt.d.s',
|
||||
'cvt.d.w',
|
||||
'cvt.d.l',
|
||||
'cvt.w.s',
|
||||
'cvt.w.d',
|
||||
'cvt.l.s',
|
||||
'cvt.l.d',
|
||||
'round.w.s',
|
||||
'round.w.d',
|
||||
'round.l.s',
|
||||
'round.l.d',
|
||||
'trunc.w.s',
|
||||
'trunc.w.d',
|
||||
'trunc.l.s',
|
||||
'trunc.l.d',
|
||||
'ceil.w.s',
|
||||
'ceil.w.d',
|
||||
'ceil.l.s',
|
||||
'ceil.l.d',
|
||||
'floor.w.s',
|
||||
'floor.w.d',
|
||||
'floor.l.s',
|
||||
'floor.l.d',
|
||||
'bc1t',
|
||||
'bc1f',
|
||||
'bc1tl',
|
||||
'bc1fl',
|
||||
'c.eq.d',
|
||||
'c.eq.s',
|
||||
'c.le.d',
|
||||
'c.le.s',
|
||||
'c.lt.d',
|
||||
'c.lt.s',
|
||||
'beqi',
|
||||
'bnei',
|
||||
'blti',
|
||||
'blei',
|
||||
'bgti',
|
||||
'bgei',
|
||||
'bltui',
|
||||
'bleui',
|
||||
'bgtui',
|
||||
'bgeui',
|
||||
'blt',
|
||||
'ble',
|
||||
'bgt',
|
||||
'bge',
|
||||
'bltu',
|
||||
'bleu',
|
||||
'bgtu',
|
||||
'bgeu',
|
||||
'seq',
|
||||
'sge',
|
||||
'sgeu',
|
||||
'sgt',
|
||||
'sgtu',
|
||||
'sle',
|
||||
'sleu',
|
||||
'sne',
|
||||
'syscall',
|
||||
'add64sub',
|
||||
'sub64sub',
|
||||
'mul64sub',
|
||||
'div64sub',
|
||||
'neg64sub',
|
||||
'not64sub',
|
||||
'or64sub',
|
||||
'sar64sub',
|
||||
'shl64sub',
|
||||
'shr64sub',
|
||||
'xor64sub',
|
||||
'end_def'
|
@ -146,7 +146,8 @@ interface
|
||||
system_avr_embedded, { 62 }
|
||||
system_i386_haiku, { 63 }
|
||||
system_arm_darwin, { 64 }
|
||||
system_x86_64_solaris { 65 }
|
||||
system_x86_64_solaris, { 65 }
|
||||
system_mips_linux { 66 }
|
||||
);
|
||||
|
||||
type
|
||||
|
@ -728,7 +728,69 @@ unit i_linux;
|
||||
);
|
||||
{$endif FPC_ARMEB}
|
||||
{$endif FPC_ARMEL}
|
||||
|
||||
{
|
||||
system_fvm32_linux_info : tsysteminfo =
|
||||
(
|
||||
system : system_mips_LINUX;
|
||||
name : 'Linux for MIPS';
|
||||
shortname : 'Linux';
|
||||
flags : [tf_needs_symbol_size];
|
||||
cpu : cpu_mips;
|
||||
unit_env : 'LINUXUNITS';
|
||||
extradefines : 'UNIX;HASUNIX';
|
||||
exeext : '';
|
||||
defext : '.def';
|
||||
scriptext : '.sh';
|
||||
smartext : '.sl';
|
||||
unitext : '.ppu';
|
||||
unitlibext : '.ppl';
|
||||
asmext : '.s';
|
||||
objext : '.o';
|
||||
resext : '.res';
|
||||
resobjext : '.or';
|
||||
sharedlibext : '.so';
|
||||
staticlibext : '.a';
|
||||
staticlibprefix : 'libp';
|
||||
sharedlibprefix : 'lib';
|
||||
sharedClibext : '.so';
|
||||
staticClibext : '.a';
|
||||
staticClibprefix : 'lib';
|
||||
sharedClibprefix : 'lib';
|
||||
// p_ext_support : false;
|
||||
Cprefix : '';
|
||||
newline : #10;
|
||||
dirsep : '/';
|
||||
files_case_relevent : true;
|
||||
assem : as_gas;
|
||||
assemextern : as_gas;
|
||||
link : nil;
|
||||
linkextern : nil;
|
||||
ar : ar_gnu_ar;
|
||||
res : res_none;
|
||||
script : script_unix;
|
||||
endian : endian_little;
|
||||
alignment :
|
||||
(
|
||||
procalign : 4;
|
||||
loopalign : 4;
|
||||
jumpalign : 0;
|
||||
constalignmin : 0;
|
||||
constalignmax : 8;
|
||||
varalignmin : 0;
|
||||
varalignmax : 8;
|
||||
localalignmin : 4;
|
||||
localalignmax : 8;
|
||||
recordalignmin : 0;
|
||||
recordalignmax : 2;
|
||||
maxCrecordalign : 4
|
||||
);
|
||||
first_parm_offset : 8;
|
||||
stacksize : 32*1024*1024;
|
||||
DllScanSupported:false;
|
||||
use_function_relative_addresses : true;
|
||||
abi : abi_default
|
||||
);
|
||||
}
|
||||
implementation
|
||||
|
||||
initialization
|
||||
@ -775,5 +837,9 @@ initialization
|
||||
set_source_info(system_arm_linux_info);
|
||||
{$endif linux}
|
||||
{$endif CPUARM}
|
||||
{$ifdef CPUMIPSEL}
|
||||
{$ifdef linux}
|
||||
set_source_info(system_mipsel_linux_info);
|
||||
{$endif linux}
|
||||
{$endif CPUMIPSEL}
|
||||
end.
|
||||
|
||||
|
@ -137,6 +137,7 @@ const
|
||||
{$ifdef sparc} platform_select='-b elf32-sparc -m elf32_sparc';{$endif}
|
||||
{$ifdef arm} platform_select='';{$endif} {unknown :( }
|
||||
{$ifdef m68k} platform_select='';{$endif} {unknown :( }
|
||||
{$ifdef mips} platform_select='';{$endif} {unknown :( }
|
||||
|
||||
var
|
||||
defdynlinker: string;
|
||||
@ -1163,5 +1164,11 @@ initialization
|
||||
RegisterExport(system_arm_linux,texportliblinux);
|
||||
RegisterTarget(system_arm_linux_info);
|
||||
{$endif ARM}
|
||||
{$ifdef MIPS}
|
||||
RegisterExternalLinker(system_mipsel_linux_info,TLinkerLinux);
|
||||
RegisterImport(system_mipsel_linux,timportliblinux);
|
||||
RegisterExport(system_mipsel_linux,texportliblinux);
|
||||
RegisterTarget(system_mipsel_linux_info);
|
||||
{$endif MIPS}
|
||||
RegisterRes(res_elf_info,TWinLikeResourceFile);
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user