summaryrefslogtreecommitdiff
path: root/riscv_new/compiler/riscv64/cpupara.pas
diff options
context:
space:
mode:
Diffstat (limited to 'riscv_new/compiler/riscv64/cpupara.pas')
-rw-r--r--riscv_new/compiler/riscv64/cpupara.pas61
1 files changed, 18 insertions, 43 deletions
diff --git a/riscv_new/compiler/riscv64/cpupara.pas b/riscv_new/compiler/riscv64/cpupara.pas
index 01b7b3586c..511dd5edb4 100644
--- a/riscv_new/compiler/riscv64/cpupara.pas
+++ b/riscv_new/compiler/riscv64/cpupara.pas
@@ -172,7 +172,7 @@ implementation
result := true;
procvardef,
recorddef:
- result := (def.size > 8);
+ result := (def.size > 16);
arraydef:
result := (tarraydef(def).highrange >= tarraydef(def).lowrange) or
is_open_array(def) or
@@ -196,13 +196,6 @@ implementation
{ general rule: passed in registers -> returned in registers }
result:=push_addr_param(vs_value,def,pd.proccalloption);
-
- case def.typ of
- procvardef:
- result:=def.size>8;
- recorddef:
- result:=true;
- end;
end;
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
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;
function tcpuparamanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint;
@@ -415,6 +381,15 @@ implementation
paracgsize:=def_cgsize(locdef);
end;
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 }
while (paralen > 0) do begin
paraloc := para.add_location;