* 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:
sergei 2013-02-18 04:20:10 +00:00
parent 2281a63116
commit 30247d8961
3 changed files with 35 additions and 144 deletions

View File

@ -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

View File

@ -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;

View File

@ -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}