mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 15:31:29 +01:00 
			
		
		
		
	 a25ebbba3e
			
		
	
	
		a25ebbba3e
		
	
	
	
	
		
			
			o separate information for reading and writing, because e.g. in a
     try-block, only the writes to local variables and parameters are
     volatile (they have to be committed immediately in case the next
     instruction causes an exception)
   o for now, only references to absolute memory addresses are marked
     as volatile
   o the volatily information is (should be) properly maintained throughout
     all code generators for all archictures with this patch
   o no optimizers or other compiler infrastructure uses the volatility
     information yet
   o this functionality is not (yet) exposed at the language level, it
     is only for internal code generator use right now
git-svn-id: trunk@34996 -
		
	
			
		
			
				
	
	
		
			178 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|     Copyright (c) 1998-2002 by Florian Klaempfl
 | |
| 
 | |
|     This unit implements the register allocator for m68k
 | |
| 
 | |
|     This program is free software; you can redistribute it and/or modify
 | |
|     it under the terms of the GNU General Public License as published by
 | |
|     the Free Software Foundation; either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU General Public License
 | |
|     along with this program; if not, write to the Free Software
 | |
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
| 
 | |
|  ****************************************************************************
 | |
| }
 | |
| 
 | |
| unit rgcpu;
 | |
| 
 | |
| {$i fpcdefs.inc}
 | |
| 
 | |
|   interface
 | |
| 
 | |
|      uses
 | |
|        aasmbase,aasmtai,aasmdata,aasmsym,aasmcpu,
 | |
|        cgbase,cgutils,cpubase,
 | |
|        rgobj;
 | |
| 
 | |
|      type
 | |
|        trgcpu = class(trgobj)
 | |
|          procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
 | |
|          procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
 | |
|          function do_spill_replace(list : TAsmList;instr : tai_cpu_abstract_sym; orgreg : tsuperregister;const spilltemp : treference) : boolean; override;
 | |
|        end;
 | |
| 
 | |
|   implementation
 | |
| 
 | |
|     uses
 | |
|       cutils,cgobj,verbose,globtype,globals,cpuinfo;
 | |
| 
 | |
|     { returns True if source operand of MOVE can be replaced with spilltemp when its destination is ref^. }
 | |
|     function isvalidmovedest(ref: preference): boolean; inline;
 | |
|       begin
 | |
|         { The following is for Coldfire, for other CPUs it maybe can be relaxed. }
 | |
|         result:=(ref^.symbol=nil) and (ref^.scalefactor<=1) and
 | |
|           (ref^.index=NR_NO) and (ref^.base<>NR_NO) and (ref^.offset>=low(smallint)) and
 | |
|           (ref^.offset<=high(smallint));
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
 | |
|       var
 | |
|         helpins  : tai;
 | |
|         tmpref   : treference;
 | |
|         helplist : tasmlist;
 | |
|         hreg     : tregister;
 | |
|       begin
 | |
|         if (abs(spilltemp.offset)>32767) and (current_settings.cputype in (cpu_coldfire + [cpu_mc68000])) then
 | |
|           begin
 | |
|             helplist:=tasmlist.create;
 | |
| 
 | |
|             if getregtype(tempreg)=R_INTREGISTER then
 | |
|               hreg:=tempreg
 | |
|             else
 | |
|               hreg:=cg.getintregister(helplist,OS_ADDR);
 | |
| {$ifdef DEBUG_SPILLING}
 | |
|             helplist.concat(tai_comment.Create(strpnew('Spilling: Read, large offset')));
 | |
| {$endif}
 | |
| 
 | |
|             helplist.concat(taicpu.op_const_reg(A_MOVE,S_L,spilltemp.offset,hreg));
 | |
|             reference_reset_base(tmpref,spilltemp.base,0,sizeof(aint),[]);
 | |
|             tmpref.index:=hreg;
 | |
| 
 | |
|             helpins:=spilling_create_load(tmpref,tempreg);
 | |
|             helplist.concat(helpins);
 | |
|             list.insertlistafter(pos,helplist);
 | |
|             helplist.free;
 | |
|           end
 | |
|         else
 | |
|           inherited;
 | |
|       end;
 | |
| 
 | |
| 
 | |
|     procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
 | |
|       var
 | |
|         tmpref   : treference;
 | |
|         helplist : tasmlist;
 | |
|         hreg     : tregister;
 | |
|       begin
 | |
|         if (abs(spilltemp.offset)>32767) and (current_settings.cputype in (cpu_coldfire + [cpu_mc68000])) then
 | |
|           begin
 | |
|             helplist:=tasmlist.create;
 | |
| 
 | |
|             if getregtype(tempreg)=R_INTREGISTER then
 | |
|               hreg:=getregisterinline(helplist,[R_SUBWHOLE])
 | |
|             else
 | |
|               hreg:=cg.getintregister(helplist,OS_ADDR);
 | |
| {$ifdef DEBUG_SPILLING}
 | |
|             helplist.concat(tai_comment.Create(strpnew('Spilling: Write, large offset')));
 | |
| {$endif}
 | |
| 
 | |
|             helplist.concat(taicpu.op_const_reg(A_MOVE,S_L,spilltemp.offset,hreg));
 | |
|             reference_reset_base(tmpref,spilltemp.base,0,sizeof(aint),[]);
 | |
|             tmpref.index:=hreg;
 | |
| 
 | |
|             helplist.concat(spilling_create_store(tempreg,tmpref));
 | |
|             if getregtype(tempreg)=R_INTREGISTER then
 | |
|               ungetregisterinline(helplist,hreg);
 | |
| 
 | |
|             list.insertlistafter(pos,helplist);
 | |
|             helplist.free;
 | |
|           end
 | |
|         else
 | |
|           inherited;
 | |
|     end;
 | |
| 
 | |
| 
 | |
|     function trgcpu.do_spill_replace(list : TAsmList;instr : tai_cpu_abstract_sym; orgreg : tsuperregister;const spilltemp : treference) : boolean;
 | |
|       var
 | |
|         opidx: longint;
 | |
|       begin
 | |
|         result:=false;
 | |
|         opidx:=-1;
 | |
|         if (abs(spilltemp.offset)>32767) and (current_settings.cputype in cpu_coldfire) then
 | |
|           exit;
 | |
|         case instr.ops of
 | |
|           1:
 | |
|             begin
 | |
|               if (instr.oper[0]^.typ=top_reg) and (getregtype(instr.oper[0]^.reg)=regtype) and
 | |
|                 ((instr.opcode=A_TST) or (instr.opcode=A_CLR)) then
 | |
|                 begin
 | |
|                   if get_alias(getsupreg(instr.oper[0]^.reg))<>orgreg then
 | |
|                     InternalError(2014080101);
 | |
|                   opidx:=0;
 | |
|                 end;
 | |
|             end;
 | |
|           2:
 | |
|             begin
 | |
|               if (instr.oper[0]^.typ=top_reg) and (getregtype(instr.oper[0]^.reg)=regtype) and
 | |
|                 (get_alias(getsupreg(instr.oper[0]^.reg))=orgreg) then
 | |
|                 begin
 | |
|                   { source can be replaced if dest is register... }
 | |
|                   if ((instr.oper[1]^.typ=top_reg) and (instr.opcode in [A_MOVE,A_ADD,A_SUB,A_AND,A_OR,A_CMP])) or
 | |
|                     {... or a "simple" reference in case of MOVE }
 | |
|                     ((instr.opcode=A_MOVE) and (instr.oper[1]^.typ=top_ref) and isvalidmovedest(instr.oper[1]^.ref)) then
 | |
|                     opidx:=0;
 | |
|                 end
 | |
|               else if (instr.oper[1]^.typ=top_reg) and (getregtype(instr.oper[1]^.reg)=regtype) and
 | |
|                 (get_alias(getsupreg(instr.oper[1]^.reg))=orgreg) and
 | |
|                 ((
 | |
|                   (instr.opcode in [A_MOVE,A_ADD,A_SUB,A_AND,A_OR]) and
 | |
|                   (instr.oper[0]^.typ=top_reg) and not
 | |
|                   (isaddressregister(instr.oper[0]^.reg))
 | |
|                 ) or
 | |
|                 (instr.opcode in [A_ADDQ,A_SUBQ,A_MOV3Q])) then
 | |
|                 opidx:=1;
 | |
|             end;
 | |
|         end;
 | |
| 
 | |
|         if (opidx<0) then
 | |
|           exit;
 | |
|         instr.oper[opidx]^.typ:=top_ref;
 | |
|         new(instr.oper[opidx]^.ref);
 | |
|         instr.oper[opidx]^.ref^:=spilltemp;
 | |
|         case taicpu(instr).opsize of
 | |
|           S_B: inc(instr.oper[opidx]^.ref^.offset,3);
 | |
|           S_W: inc(instr.oper[opidx]^.ref^.offset,2);
 | |
|         end;
 | |
|         result:=true;
 | |
|       end;
 | |
| 
 | |
| end.
 |