summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2013-01-13 18:24:06 +0000
committersergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2013-01-13 18:24:06 +0000
commit7152c3672bf7aee070d9116997ededc9793a0928 (patch)
tree0f0c653a629ee000051f4789e9790485d11be071
parent6158b7d8ed7496d77fbf4b92cbf2b1b441772fa7 (diff)
downloadfpc-7152c3672bf7aee070d9116997ededc9793a0928.tar.gz
* MIPS code generator fixes and improvements:
- removed a_jmp_cond, it's not virtual and not applicable to this CPU. * a_loadfpu_reg_cgpara: use direct register moves for simple destinations. * g_concatcopy: don't take address of source/destination for small amounts of data if possible, for single 32-bit moves this reduces number of generated instructions from 4 to 2. * g_intf_wrapper: 'Self' is in R4 (a0), not R2. Fixes test/tinterface1.pp. * mips/cpupara.pas: for functions with result returned in parameter, pass its address in a0 only if result is a record. ABI does not specify behavior for types except records/unions. At the same time, Pascal code relies on the fact that results like strings/interfaces does not change their locations, i.e. "function foo(<self>): IInterface" can be invoked as "procedure foo(<self>, out obj)". This fixes test/tdel1.pp and some Variant-related tests. git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@23377 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/mips/cgcpu.pas54
-rw-r--r--compiler/mips/cpupara.pas6
2 files changed, 41 insertions, 19 deletions
diff --git a/compiler/mips/cgcpu.pas b/compiler/mips/cgcpu.pas
index 13c90820d0..e9c5131ba6 100644
--- a/compiler/mips/cgcpu.pas
+++ b/compiler/mips/cgcpu.pas
@@ -79,7 +79,6 @@ type
procedure a_cmp_reg_reg_label(list: tasmlist; size: tcgsize; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); override;
procedure a_jmp_always(List: tasmlist; l: TAsmLabel); override;
procedure a_jmp_name(list: tasmlist; const s: string); override;
- procedure a_jmp_cond(list: tasmlist; cond: TOpCmp; l: tasmlabel); { override;}
procedure g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef); override;
procedure g_overflowCheck_loc(List: tasmlist; const Loc: TLocation; def: TDef; ovloc: tlocation); override;
procedure g_proc_entry(list: tasmlist; localsize: longint; nostackframe: boolean); override;
@@ -680,6 +679,11 @@ procedure TCGMIPS.a_loadfpu_reg_cgpara(list: tasmlist; size: tcgsize; const r: t
var
href: treference;
begin
+ if paraloc.Location^.next=nil then
+ begin
+ inherited a_loadfpu_reg_cgpara(list,size,r,paraloc);
+ exit;
+ end;
tg.GetTemp(list, TCGSize2Size[size], TCGSize2Size[size], tt_normal, href);
a_loadfpu_reg_ref(list, size, size, r, href);
a_loadfpu_ref_cgpara(list, size, href, paraloc);
@@ -1340,12 +1344,6 @@ begin
end;
-procedure TCGMIPS.a_jmp_cond(list: tasmlist; cond: TOpCmp; l: TAsmLabel);
-begin
- internalerror(200701181);
-end;
-
-
procedure TCGMIPS.g_overflowCheck(List: tasmlist; const Loc: TLocation; def: TDef);
begin
// this is an empty procedure
@@ -1704,6 +1702,15 @@ var
lab: tasmlabel;
Count, count2: aint;
ai : TaiCpu;
+
+ function reference_is_reusable(const ref: treference): boolean;
+ begin
+ result:=(ref.base<>NR_NO) and (ref.index=NR_NO) and
+ (ref.symbol=nil) and
+ (ref.alignment>=sizeof(aint)) and
+ (ref.offset>=simm16lo) and (ref.offset+len<=simm16hi);
+ end;
+
begin
if len > high(longint) then
internalerror(2002072704);
@@ -1712,16 +1719,26 @@ begin
g_concatcopy_move(list, Source, dest, len)
else
begin
- reference_reset(src,sizeof(aint));
- reference_reset(dst,sizeof(aint));
- { load the address of source into src.base }
- src.base := GetAddressRegister(list);
- a_loadaddr_ref_reg(list, Source, src.base);
- { load the address of dest into dst.base }
- dst.base := GetAddressRegister(list);
- a_loadaddr_ref_reg(list, dest, dst.base);
- { generate a loop }
Count := len div 4;
+ if (count<=4) and reference_is_reusable(source) then
+ src:=source
+ else
+ begin
+ reference_reset(src,sizeof(aint));
+ { load the address of source into src.base }
+ src.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, Source, src.base);
+ end;
+ if (count<=4) and reference_is_reusable(dest) then
+ dst:=dest
+ else
+ begin
+ reference_reset(dst,sizeof(aint));
+ { load the address of dest into dst.base }
+ dst.base := GetAddressRegister(list);
+ a_loadaddr_ref_reg(list, dest, dst.base);
+ end;
+ { generate a loop }
if Count > 4 then
begin
{ the offsets are zero after the a_loadaddress_ref_reg and just }
@@ -1855,7 +1872,10 @@ procedure TCGMIPS.g_intf_wrapper(list: tasmlist; procdef: tprocdef; const labeln
var
href: treference;
begin
- reference_reset_base(href, NR_R2, 0, sizeof(aint)); { return value }
+ { TODO: Hardcoded register is ugly!
+ Look for the 'self' parameter again? g_adjust_self_value() does it right before,
+ but the result is local to g_adjust_self_value. }
+ reference_reset_base(href, NR_R4, 0, sizeof(aint));
cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_VMT);
end;
diff --git a/compiler/mips/cpupara.pas b/compiler/mips/cpupara.pas
index ffd625e780..d8513a5fad 100644
--- a/compiler/mips/cpupara.pas
+++ b/compiler/mips/cpupara.pas
@@ -200,7 +200,8 @@ implementation
retdef:=forcetempdef
else
retdef:=p.returndef;
- if ret_in_param(retdef,p.proccalloption) then
+ if ret_in_param(retdef,p.proccalloption) and
+ (retdef.typ=recorddef) then
begin
if intparareg=0 then
inc(intparareg);
@@ -372,7 +373,8 @@ implementation
else
paraloc^.size:=paracgsize;
{ ret in param? }
- if vo_is_funcret in hp.varoptions then
+ if (vo_is_funcret in hp.varoptions) and
+ (hp.vardef.typ=recorddef) then
begin
{ This should be the first parameter }
if (side=calleeside) and assigned(current_procinfo) then