瀏覽代碼

* 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: trunk@23377 -

sergei 12 年之前
父節點
當前提交
162896e7d7
共有 2 個文件被更改,包括 41 次插入19 次删除
  1. 37 17
      compiler/mips/cgcpu.pas
  2. 4 2
      compiler/mips/cpupara.pas

+ 37 - 17
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;
 

+ 4 - 2
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