mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 05:59:37 +01:00 
			
		
		
		
	m68k: for cdecls with the SVR4 ABI return results both in A0 and D0
git-svn-id: trunk@36588 -
This commit is contained in:
		
							parent
							
								
									bc53a908c9
								
							
						
					
					
						commit
						b481129f4e
					
				@ -1876,11 +1876,11 @@ unit cgcpu;
 | 
			
		||||
                    { point to nowhere!                                   }
 | 
			
		||||
 | 
			
		||||
                    { Instead of doing a slow copy of the return address while trying    }
 | 
			
		||||
                    { to feed it to the RTS instruction, load the PC to A0 (scratch reg) }
 | 
			
		||||
                    { then free up the stack allocated for paras, then use a JMP (A0) to }
 | 
			
		||||
                    { to feed it to the RTS instruction, load the PC to A1 (scratch reg) }
 | 
			
		||||
                    { then free up the stack allocated for paras, then use a JMP (A1) to }
 | 
			
		||||
                    { return to the caller with the paras freed. (KB) }
 | 
			
		||||
 | 
			
		||||
                    hregister:=NR_A0;
 | 
			
		||||
                    hregister:=NR_A1;
 | 
			
		||||
                    cg.a_reg_alloc(list,hregister);
 | 
			
		||||
                    reference_reset_base(ref,NR_STACK_POINTER_REG,0,4,[]);
 | 
			
		||||
                    list.concat(taicpu.op_ref_reg(A_MOVE,S_L,ref,hregister));
 | 
			
		||||
 | 
			
		||||
@ -279,8 +279,8 @@ unit cpubase;
 | 
			
		||||
{ TODO: FIX ME!!! pic offset reg conflicts with frame pointer?}
 | 
			
		||||
      NR_PIC_OFFSET_REG = NR_A5;
 | 
			
		||||
      { Return address for DWARF }
 | 
			
		||||
{ TODO: just a guess!}
 | 
			
		||||
      NR_RETURN_ADDRESS_REG = NR_A0;
 | 
			
		||||
      RS_RETURN_ADDRESS_REG = RS_A0;
 | 
			
		||||
      { Results are returned in this register (32-bit values) }
 | 
			
		||||
      NR_FUNCTION_RETURN_REG = NR_D0;
 | 
			
		||||
      RS_FUNCTION_RETURN_REG = RS_D0;
 | 
			
		||||
 | 
			
		||||
@ -168,8 +168,9 @@ unit cpupara;
 | 
			
		||||
 | 
			
		||||
    function tcpuparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
 | 
			
		||||
      var
 | 
			
		||||
        paraloc : pcgparalocation;
 | 
			
		||||
        paraloc    : pcgparalocation;
 | 
			
		||||
        retcgsize  : tcgsize;
 | 
			
		||||
        retregtype : tregistertype;
 | 
			
		||||
      begin
 | 
			
		||||
        if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
 | 
			
		||||
          exit;
 | 
			
		||||
@ -223,10 +224,39 @@ unit cpupara;
 | 
			
		||||
               paraloc^.loc:=LOC_REGISTER;
 | 
			
		||||
               paraloc^.size:=retcgsize;
 | 
			
		||||
               paraloc^.def:=result.def;
 | 
			
		||||
               if side=callerside then
 | 
			
		||||
                 paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
 | 
			
		||||
 | 
			
		||||
               { GCC (and SVR4 in general maybe?) requires a pointer result on the A0
 | 
			
		||||
                 register, as well as D0. So we init the result to be A0, then copy
 | 
			
		||||
                 it also to D0 in hlcg.gen_load_loc_function_result. This is not pretty,
 | 
			
		||||
                 but we don't really have an architecture for funcretlocs in two
 | 
			
		||||
                 separate locations.
 | 
			
		||||
 | 
			
		||||
                 We also have to figure out a better switch for this, because this is
 | 
			
		||||
                 now compiler and platform specific... (KB) }
 | 
			
		||||
 | 
			
		||||
               if (tprocdef(p).proccalloption in [pocall_cdecl,pocall_cppdecl]) and
 | 
			
		||||
                  (target_info.system in [system_m68k_linux]) and
 | 
			
		||||
                  assigned(result.def) and
 | 
			
		||||
                  (result.def.typ in [stringdef,pointerdef,classrefdef,objectdef,
 | 
			
		||||
                                      procvardef,procdef,arraydef,formaldef]) then
 | 
			
		||||
                 retregtype:=R_ADDRESSREGISTER
 | 
			
		||||
               else
 | 
			
		||||
                 paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
 | 
			
		||||
                 retregtype:=R_INTREGISTER;
 | 
			
		||||
 | 
			
		||||
               if retregtype = R_ADDRESSREGISTER then
 | 
			
		||||
                 begin
 | 
			
		||||
                   if side=callerside then
 | 
			
		||||
                     paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize))
 | 
			
		||||
                   else
 | 
			
		||||
                     paraloc^.register:=newreg(R_ADDRESSREGISTER,RS_RETURN_ADDRESS_REG,cgsize2subreg(R_ADDRESSREGISTER,retcgsize));
 | 
			
		||||
                 end
 | 
			
		||||
               else
 | 
			
		||||
                 begin
 | 
			
		||||
                   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));
 | 
			
		||||
                 end;
 | 
			
		||||
             end;
 | 
			
		||||
          end;
 | 
			
		||||
      end;
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,8 @@ interface
 | 
			
		||||
      procedure a_bit_set_reg_ref(list: TAsmList; doset: boolean; fromsize, tosize: tdef; bitnumber: tregister; const ref: treference); override;
 | 
			
		||||
      procedure a_bit_set_const_ref(list: TAsmList; doset: boolean; destsize: tdef; bitnumber: tcgint; const ref: treference); override;
 | 
			
		||||
      procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
 | 
			
		||||
 | 
			
		||||
      procedure gen_load_loc_function_result(list: TAsmList; vardef: tdef; const l: tlocation);override;
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
  procedure create_hlcodegen;
 | 
			
		||||
@ -55,7 +57,8 @@ implementation
 | 
			
		||||
    aasmtai, aasmcpu,
 | 
			
		||||
    defutil,
 | 
			
		||||
    hlcgobj,
 | 
			
		||||
    cpuinfo, cgobj, cpubase, cgcpu;
 | 
			
		||||
    cpuinfo, cgobj, cpubase, cgcpu,
 | 
			
		||||
    parabase, procinfo;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -241,6 +244,26 @@ implementation
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  procedure thlcgcpu.gen_load_loc_function_result(list: TAsmList; vardef: tdef; const l: tlocation);
 | 
			
		||||
    var
 | 
			
		||||
      cgpara: tcgpara;
 | 
			
		||||
    begin
 | 
			
		||||
      inherited;
 | 
			
		||||
 | 
			
		||||
      { Kludge:
 | 
			
		||||
        GCC (and SVR4 in general maybe?) requires a pointer
 | 
			
		||||
        result on the A0 register, as well as D0. So when we
 | 
			
		||||
        have a result in A0, also copy it to D0. See the decision
 | 
			
		||||
        making code in tcpuparamanager.get_funcretloc (KB) }
 | 
			
		||||
      cgpara:=current_procinfo.procdef.funcretloc[calleeside];
 | 
			
		||||
      if ((cgpara.location^.loc = LOC_REGISTER) and
 | 
			
		||||
          (isaddressregister(cgpara.location^.register))) then
 | 
			
		||||
        begin
 | 
			
		||||
          cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_RETURN_ADDRESS_REG,NR_FUNCTION_RESULT_REG);
 | 
			
		||||
        end;
 | 
			
		||||
    end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  procedure create_hlcodegen;
 | 
			
		||||
    begin
 | 
			
		||||
      hlcg:=thlcgcpu.create;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user