Browse Source

Updated dynlinker filename.
Fix passing of vararg register pairs.
Fix passing of big record, and return of records.
Disabled framepointer elimination for the time being.

git-svn-id: branches/laksen/riscv_new@39519 -

Jeppe Johansen 7 years ago
parent
commit
76dda5813e
3 changed files with 21 additions and 46 deletions
  1. 2 2
      compiler/psub.pas
  2. 18 43
      compiler/riscv64/cpupara.pas
  3. 1 1
      compiler/systems/t_linux.pas

+ 2 - 2
compiler/psub.pas

@@ -1002,7 +1002,7 @@ implementation
       begin
       begin
         tg:=tgobjclass.create;
         tg:=tgobjclass.create;
 
 
-{$if defined(i386) or defined(x86_64) or defined(arm) or defined(riscv32) or defined(riscv64)}
+{$if defined(i386) or defined(x86_64) or defined(arm)}
 {$if defined(arm)}
 {$if defined(arm)}
         { frame and stack pointer must be always the same on arm thumb so it makes no
         { frame and stack pointer must be always the same on arm thumb so it makes no
           sense to fiddle with a frame pointer }
           sense to fiddle with a frame pointer }
@@ -1100,7 +1100,7 @@ implementation
 {$endif defined(arm)}
 {$endif defined(arm)}
               end;
               end;
           end;
           end;
-{$endif defined(x86) or defined(arm) or defined(riscv32) or defined(riscv64)}
+{$endif defined(x86) or defined(arm)}
         { set the start offset to the start of the temp area in the stack }
         { set the start offset to the start of the temp area in the stack }
         set_first_temp_offset;
         set_first_temp_offset;
       end;
       end;

+ 18 - 43
compiler/riscv64/cpupara.pas

@@ -172,7 +172,7 @@ implementation
             result := true;
             result := true;
           procvardef,
           procvardef,
           recorddef:
           recorddef:
-            result := (def.size > 8);
+            result := (def.size > 16);
           arraydef:
           arraydef:
             result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
             result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
               is_open_array(def) or
               is_open_array(def) or
@@ -196,13 +196,6 @@ implementation
 
 
         { general rule: passed in registers -> returned in registers }
         { general rule: passed in registers -> returned in registers }
         result:=push_addr_param(vs_value,def,pd.proccalloption);
         result:=push_addr_param(vs_value,def,pd.proccalloption);
-
-        case def.typ of
-          procvardef:
-            result:=def.size>8;
-          recorddef:
-            result:=true;
-        end;
       end;
       end;
 
 
     procedure tcpuparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
     procedure tcpuparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@@ -224,41 +217,14 @@ implementation
         if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
         if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
           exit;
           exit;
 
 
-        paraloc:=result.add_location;
-        { Return in FPU register? }
-        if result.def.typ=floatdef then
-          begin
-            if (p.proccalloption in [pocall_softfloat]) or
-               (cs_fp_emulation in current_settings.moduleswitches) or
-               (current_settings.fputype in [fpu_soft]) then
-              begin
-                paraloc^.loc:=LOC_REGISTER;
-                if side=callerside then
-                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
-                else
-                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
-                paraloc^.size:=retcgsize;
-                paraloc^.def:=result.def;
-              end
-            else
-              begin
-                paraloc^.loc:=LOC_FPUREGISTER;
-                paraloc^.register:=NR_FPU_RESULT_REG;
-                paraloc^.size:=retcgsize;
-                paraloc^.def:=result.def;
-              end;
-          end
-        else
-         { Return in register }
-          begin
-            paraloc^.loc:=LOC_REGISTER;
-            if side=callerside then
-              paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
-            else
-              paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
-            paraloc^.size:=retcgsize;
-            paraloc^.def:=result.def;
-          end;
+         { in this case, it must be returned in registers as if it were passed
+           as the first parameter }
+         init_values(nextintreg,nextfloatreg,nextmmreg,stack_offset);
+         create_paraloc_for_def(result,vs_value,result.def,nextfloatreg,nextintreg,stack_offset,false,false,side,p);
+         { sanity check (LOC_VOID for empty records) }
+         if not assigned(result.location) or
+            not(result.location^.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_VOID]) then
+           internalerror(2014113001);
       end;
       end;
 
 
     function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint;
     function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint;
@@ -415,6 +381,15 @@ implementation
             paracgsize:=def_cgsize(locdef);
             paracgsize:=def_cgsize(locdef);
           end;
           end;
         firstparaloc:=true;
         firstparaloc:=true;
+
+        // Parameters passed in 2 registers are passed in a register starting with an even number.
+        if isVararg and
+           (paralen > 8) and
+           (loc = LOC_REGISTER) and
+           (nextintreg <= RS_X17) and
+           odd(nextintreg) then
+          inc(nextintreg);
+
         { can become < 0 for e.g. 3-byte records }
         { can become < 0 for e.g. 3-byte records }
         while (paralen > 0) do begin
         while (paralen > 0) do begin
           paraloc := para.add_location;
           paraloc := para.add_location;

+ 1 - 1
compiler/systems/t_linux.pas

@@ -238,7 +238,7 @@ const defdynlinker='/lib/ld-linux-aarch64.so.1';
   const defdynlinker='/lib32/ld.so.1';
   const defdynlinker='/lib32/ld.so.1';
 {$endif riscv32}
 {$endif riscv32}
 {$ifdef riscv64}
 {$ifdef riscv64}
-  const defdynlinker='/lib/ld.so.1';
+  const defdynlinker='/lib/ld-linux-riscv64-lp64d.so.1';
 {$endif riscv64}
 {$endif riscv64}