mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 07:28:26 +02:00
* MIPS: fixed parameter handling for big-endian targets, and removed a lot of garbage.
* Parameters passed in registers are no longer forced to stack, therefore assembler routines using 'lw' instruction to load such parameters must have it changed to 'move' (tb0072.pp). git-svn-id: trunk@23627 -
This commit is contained in:
parent
2281a63116
commit
30247d8961
@ -710,11 +710,9 @@ procedure TCGMIPS.a_load_reg_ref(list: tasmlist; FromSize, ToSize: TCGSize; reg:
|
||||
var
|
||||
op: tasmop;
|
||||
begin
|
||||
|
||||
if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
|
||||
fromsize := tosize;
|
||||
case fromsize of
|
||||
{ signed integer registers }
|
||||
if (TCGSize2Size[fromsize] < TCGSize2Size[tosize]) then
|
||||
a_load_reg_reg(list,fromsize,tosize,reg,reg);
|
||||
case tosize of
|
||||
OS_8,
|
||||
OS_S8:
|
||||
Op := A_SB;
|
||||
@ -1394,7 +1392,7 @@ begin
|
||||
if nostackframe then
|
||||
exit;
|
||||
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
||||
a_reg_alloc(list,NR_FRAME_POINTER_REG);
|
||||
|
||||
helplist:=TAsmList.Create;
|
||||
@ -1434,7 +1432,7 @@ begin
|
||||
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
||||
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||
include(saveregs,RS_R31);
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
||||
include(saveregs,RS_FRAME_POINTER_REG);
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
@ -1561,44 +1559,11 @@ begin
|
||||
// href.offset:=register_offset[i]+Localsize
|
||||
//else
|
||||
href.offset:=register_offset[i];
|
||||
{$ifdef MIPSEL}
|
||||
if cs_asm_source in current_settings.globalswitches then
|
||||
list.concat(tai_comment.Create(strpnew('Var '+
|
||||
register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
|
||||
+' saved to offset '+tostr(href.offset))));
|
||||
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
|
||||
{$else not MIPSEL, for big endian, size matters}
|
||||
case register_size[i] of
|
||||
OS_8,
|
||||
OS_S8:
|
||||
StoreOp := A_SB;
|
||||
OS_16,
|
||||
OS_S16:
|
||||
StoreOp := A_SH;
|
||||
OS_32,
|
||||
OS_NO,
|
||||
OS_F32,
|
||||
OS_S32:
|
||||
StoreOp := A_SW;
|
||||
OS_F64,
|
||||
OS_64,
|
||||
OS_S64:
|
||||
begin
|
||||
{$ifdef cpu64bitalu}
|
||||
StoreOp:=A_SD;
|
||||
{$else not cpu64bitalu}
|
||||
StoreOp:= A_SW;
|
||||
{$endif not cpu64bitalu}
|
||||
end
|
||||
else
|
||||
internalerror(2012061801);
|
||||
end;
|
||||
if cs_asm_source in current_settings.globalswitches then
|
||||
list.concat(tai_comment.Create(strpnew('Var '+
|
||||
register_name[i]+' Register '+std_regname(newreg(R_INTREGISTER,reg,R_SUBWHOLE))
|
||||
+' saved to offset '+tostr(href.offset))));
|
||||
list.concat(taicpu.op_reg_ref(StoreOp, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
|
||||
{$endif}
|
||||
end;
|
||||
end;
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
@ -1646,7 +1611,7 @@ begin
|
||||
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
|
||||
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||
include(saveregs,RS_R31);
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) then
|
||||
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then
|
||||
include(saveregs,RS_FRAME_POINTER_REG);
|
||||
if (cs_create_pic in current_settings.moduleswitches) and
|
||||
(pi_needs_got in current_procinfo.flags) then
|
||||
|
@ -216,31 +216,6 @@ implementation
|
||||
begin
|
||||
if intparareg=0 then
|
||||
inc(intparareg);
|
||||
if side=calleeside then
|
||||
begin
|
||||
result.reset;
|
||||
paraloc:=result.add_location;
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.reference.index:=NR_STACK_POINTER_REG;
|
||||
{ return is at offset zero }
|
||||
paraloc^.reference.offset:=0;
|
||||
paraloc^.size:=retcgsize;
|
||||
{ Reserve first register for ret_in_param }
|
||||
if assigned(current_procinfo) then
|
||||
begin
|
||||
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
|
||||
TMIPSProcInfo(current_procinfo).register_size[0]:=retcgsize;
|
||||
TMIPSProcInfo(current_procinfo).register_name[0]:='ret_in_param_result';
|
||||
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
getIntParaLoc(p,1,result);
|
||||
result.def:=retdef;
|
||||
end;
|
||||
// This is now done in set_common_funcretloc_info already
|
||||
// result.def:=getpointerdef(result.def);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
@ -350,9 +325,17 @@ implementation
|
||||
//writeln('para: ',hp.Name,' typ=',hp.vardef.typ,' paracgsize=',paracgsize,' align=',hp.vardef.alignment);
|
||||
hp.paraloc[side].reset;
|
||||
hp.paraloc[side].Alignment:=alignment;
|
||||
if paracgsize=OS_NO then
|
||||
if (paracgsize=OS_NO) or
|
||||
{ Ordinals on caller side must be promoted to machine word }
|
||||
((target_info.endian=endian_big) and // applies to little-endian too?
|
||||
(paradef.typ<>recorddef) and
|
||||
(side=callerside) and
|
||||
(paralen<tcgsize2size[OS_INT]))then
|
||||
begin
|
||||
paracgsize:=OS_32;
|
||||
if is_signed(paradef) then
|
||||
paracgsize:=OS_S32
|
||||
else
|
||||
paracgsize:=OS_32;
|
||||
paralen:=align(paralen,4);
|
||||
end
|
||||
else
|
||||
@ -395,48 +378,15 @@ implementation
|
||||
else
|
||||
paraloc^.size:=paracgsize;
|
||||
|
||||
{ big-endian targets require that record data stored in parameter
|
||||
registers is left-aligned }
|
||||
if (target_info.endian=endian_big) and
|
||||
(paradef.typ = recorddef) and
|
||||
(tcgsize2size[paraloc^.size] <> sizeof(aint)) then
|
||||
begin
|
||||
paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
|
||||
paraloc^.size := OS_INT;
|
||||
end;
|
||||
|
||||
{ ret in param? }
|
||||
if (vo_is_funcret in hp.varoptions) and
|
||||
is_abi_record(hp.vardef) then
|
||||
begin
|
||||
{ This should be the first parameter }
|
||||
if (side=calleeside) and assigned(current_procinfo) then
|
||||
begin
|
||||
TMIPSProcInfo(current_procinfo).register_used[0]:=true;
|
||||
TMIPSProcInfo(current_procinfo).register_name[0]:='result';
|
||||
TMIPSProcInfo(current_procinfo).register_size[0]:=paraloc^.size;
|
||||
TMIPSProcInfo(current_procinfo).register_offset[0]:=0;
|
||||
end;
|
||||
//if (intparareg<>1) then
|
||||
// Comment(V_Warning,'intparareg should be one for funcret in TMipsParaManager.create_paraloc_info_intern');
|
||||
if side=callerside then
|
||||
begin
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[0],R_SUBWHOLE);
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
if (po_nostackframe in p.procoptions) then
|
||||
paraloc^.reference.index := NR_STACK_POINTER_REG
|
||||
else
|
||||
begin
|
||||
paraloc^.reference.index := NR_FRAME_POINTER_REG;
|
||||
if assigned(current_procinfo) then
|
||||
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
|
||||
end;
|
||||
paraloc^.reference.offset:=0;
|
||||
end;
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[0],R_SUBWHOLE);
|
||||
inc(intparasize,align(tcgsize2size[paraloc^.size],sizeof(aint)));
|
||||
end
|
||||
{ In case of po_delphi_nested_cc, the parent frame pointer
|
||||
@ -470,30 +420,17 @@ implementation
|
||||
end
|
||||
else { not can use float }
|
||||
begin
|
||||
if (side=calleeside) and assigned(current_procinfo) then
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[intparareg],R_SUBWHOLE);
|
||||
|
||||
{ big-endian targets require that record data stored in parameter
|
||||
registers is left-aligned }
|
||||
if (target_info.endian=endian_big) and
|
||||
(paradef.typ=recorddef) and
|
||||
(paralen<tcgsize2size[OS_INT]) then
|
||||
begin
|
||||
TMIPSProcInfo(current_procinfo).register_used[intparareg]:=true;
|
||||
TMIPSProcInfo(current_procinfo).register_name[intparareg]:=hp.prettyname;
|
||||
TMIPSProcInfo(current_procinfo).register_size[intparareg]:=paraloc^.size;
|
||||
TMIPSProcInfo(current_procinfo).register_offset[intparareg]:=intparareg*mips_sizeof_register_param;
|
||||
end;
|
||||
if side=callerside then
|
||||
begin
|
||||
paraloc^.loc:=LOC_REGISTER;
|
||||
paraloc^.register:=newreg(R_INTREGISTER,parasupregs[intparareg],R_SUBWHOLE);
|
||||
end
|
||||
else
|
||||
begin
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
if (po_nostackframe in p.procoptions) then
|
||||
paraloc^.reference.index := NR_STACK_POINTER_REG
|
||||
else
|
||||
begin
|
||||
paraloc^.reference.index := NR_FRAME_POINTER_REG;
|
||||
if assigned(current_procinfo) then
|
||||
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
|
||||
end;
|
||||
paraloc^.reference.offset:=intparareg*mips_sizeof_register_param;
|
||||
paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
|
||||
paraloc^.size := OS_INT;
|
||||
end;
|
||||
inc(intparareg);
|
||||
inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
|
||||
@ -504,16 +441,6 @@ implementation
|
||||
paraloc^.loc:=LOC_REFERENCE;
|
||||
paraloc^.size:=int_cgsize(paralen);
|
||||
|
||||
{ Force size to multiple of 4 for records passed by value,
|
||||
to obtain correct memory layout for big endian }
|
||||
(*
|
||||
if (paradef.typ = recorddef) and
|
||||
(tcgsize2size[paraloc^.size] < tcgsize2size[OS_32]) then
|
||||
begin
|
||||
inc(paralen,tcgsize2size[OS_32]-tcgsize2size[paraloc^.size]);
|
||||
paraloc^.size := OS_32;
|
||||
end;
|
||||
*)
|
||||
if side=callerside then
|
||||
begin
|
||||
paraloc^.reference.index := NR_STACK_POINTER_REG;
|
||||
@ -530,6 +457,11 @@ implementation
|
||||
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true;
|
||||
end;
|
||||
paraloc^.reference.offset:=intparasize;
|
||||
|
||||
if (target_info.endian=endian_big) and
|
||||
(paralen<tcgsize2size[OS_INT]) and
|
||||
(paradef.typ<>recorddef) then
|
||||
inc(paraloc^.reference.offset,4-paralen);
|
||||
end;
|
||||
inc(intparasize,align(paralen,mips_sizeof_register_param));
|
||||
paralen:=0;
|
||||
@ -540,12 +472,6 @@ implementation
|
||||
{ O32 ABI reqires at least 16 bytes }
|
||||
if (intparasize < 16) then
|
||||
intparasize := 16;
|
||||
{ Increase maxpushparasize, but only if not examining itself }
|
||||
//if assigned(current_procinfo) and (side=callerside) and
|
||||
// (current_procinfo.procdef <> p) then
|
||||
// begin
|
||||
// TMIPSProcinfo(current_procinfo).allocate_push_parasize(intparasize);
|
||||
// end;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -55,8 +55,8 @@ end;
|
||||
{$ifdef CPUMIPS}
|
||||
{$define SUPPORTED}
|
||||
asm
|
||||
lw $t1,x
|
||||
lw $t2,y
|
||||
move $t1,x
|
||||
move $t2,y
|
||||
end;
|
||||
{$endif CPUMIPS}
|
||||
{$ifndef SUPPORTED}
|
||||
|
Loading…
Reference in New Issue
Block a user