From 30247d89618d2abe2b11719aa0a9c3360d022be1 Mon Sep 17 00:00:00 2001 From: sergei Date: Mon, 18 Feb 2013 04:20:10 +0000 Subject: [PATCH] * 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 - --- compiler/mips/cgcpu.pas | 47 ++------------ compiler/mips/cpupara.pas | 128 ++++++++------------------------------ tests/tbs/tb0072.pp | 4 +- 3 files changed, 35 insertions(+), 144 deletions(-) diff --git a/compiler/mips/cgcpu.pas b/compiler/mips/cgcpu.pas index efb44d5a8b..5de6567b1c 100644 --- a/compiler/mips/cgcpu.pas +++ b/compiler/mips/cgcpu.pas @@ -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 diff --git a/compiler/mips/cpupara.pas b/compiler/mips/cpupara.pas index ce3e549fa7..a40d5ef768 100644 --- a/compiler/mips/cpupara.pas +++ b/compiler/mips/cpupara.pas @@ -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 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 + (paralenrecorddef) 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; diff --git a/tests/tbs/tb0072.pp b/tests/tbs/tb0072.pp index d937dde144..8842c7a725 100644 --- a/tests/tbs/tb0072.pp +++ b/tests/tbs/tb0072.pp @@ -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}