|
@@ -105,388 +105,6 @@ implementation
|
|
|
Trgcpu
|
|
|
******************************************************************************}
|
|
|
|
|
|
-{$ifdef OLDRGX86}
|
|
|
- function trgx86.instr_spill_register(list:Taasmoutput;
|
|
|
- instr:taicpu;
|
|
|
- const r:Tsuperregisterset;
|
|
|
- const spilltemplist:Tspill_temp_list): boolean;
|
|
|
- {
|
|
|
- Spill the registers in r in this instruction. Returns true if any help
|
|
|
- registers are used. This procedure has become one big hack party, because
|
|
|
- of the huge amount of situations you can have. The irregularity of the i386
|
|
|
- instruction set doesn't help either. (DM)
|
|
|
- }
|
|
|
- var i:byte;
|
|
|
- supreg:Tsuperregister;
|
|
|
- subreg:Tsubregister;
|
|
|
- helpreg:Tregister;
|
|
|
- helpins:Taicpu;
|
|
|
- op:Tasmop;
|
|
|
- hopsize:Topsize;
|
|
|
- pos:Tai;
|
|
|
-
|
|
|
- begin
|
|
|
- {Situation examples are in intel notation, so operand order:
|
|
|
- mov eax , ebx
|
|
|
- ^^^ ^^^
|
|
|
- oper[1] oper[0]
|
|
|
- (DM)}
|
|
|
- result:=false;
|
|
|
- with taicpu(instr) do
|
|
|
- begin
|
|
|
- case ops of
|
|
|
- 0:
|
|
|
- ;
|
|
|
- 1:
|
|
|
- begin
|
|
|
- if (oper[0]^.typ=top_reg) and
|
|
|
- (getregtype(oper[0]^.reg)=regtype) then
|
|
|
- begin
|
|
|
- supreg:=getsupreg(oper[0]^.reg);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- push r20d ; r20d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
- push [ebp-12] ; Replace register by reference }
|
|
|
- { hopsize:=reg2opsize(oper[0].reg);}
|
|
|
- oper[0]^.typ:=top_ref;
|
|
|
- new(oper[0]^.ref);
|
|
|
- oper[0]^.ref^:=spilltemplist[supreg];
|
|
|
- { oper[0]^.ref^.size:=hopsize;}
|
|
|
- end;
|
|
|
- end;
|
|
|
- if oper[0]^.typ=top_ref then
|
|
|
- begin
|
|
|
- supreg:=getsupreg(oper[0]^.ref^.base);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- push [r21d+4*r22d] ; r21d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r23d,[ebp-12] ; Use a help register
|
|
|
- push [r23d+4*r22d] ; Replace register by helpregister }
|
|
|
- subreg:=getsubreg(oper[0]^.ref^.base);
|
|
|
- if oper[0]^.ref^.index=NR_NO then
|
|
|
- pos:=Tai(previous)
|
|
|
- else
|
|
|
- pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID);
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- oper[0]^.ref^.base:=helpreg;
|
|
|
- end;
|
|
|
- supreg:=getsupreg(oper[0]^.ref^.index);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- push [r21d+4*r22d] ; r22d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r23d,[ebp-12] ; Use a help register
|
|
|
- push [r21d+4*r23d] ; Replace register by helpregister }
|
|
|
- subreg:=getsubreg(oper[0]^.ref^.index);
|
|
|
- if oper[0]^.ref^.base=NR_NO then
|
|
|
- pos:=Tai(instr.previous)
|
|
|
- else
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID);
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- oper[0]^.ref^.index:=helpreg;
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
- 2,
|
|
|
- 3 :
|
|
|
- begin
|
|
|
- { Opcodes with 3 registers are shrd/shld, where the 3rd operand is const or CL,
|
|
|
- that doesn't need spilling }
|
|
|
-
|
|
|
- { First spill the registers from the references. This is
|
|
|
- required because the reference can be moved from this instruction
|
|
|
- to a MOV instruction when spilling of the register operand is done }
|
|
|
- for i:=0 to 1 do
|
|
|
- if oper[i]^.typ=top_ref then
|
|
|
- begin
|
|
|
- supreg:=getsupreg(oper[i]^.ref^.base);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- add r20d,[r21d+4*r22d] ; r21d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r23d,[ebp-12] ; Use a help register
|
|
|
- add r20d,[r23d+4*r22d] ; Replace register by helpregister }
|
|
|
- subreg:=getsubreg(oper[i]^.ref^.base);
|
|
|
- if i=1 then
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),RS_INVALID)
|
|
|
- else
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID);
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- oper[i]^.ref^.base:=helpreg;
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- end;
|
|
|
- supreg:=getsupreg(oper[i]^.ref^.index);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- add r20d,[r21d+4*r22d] ; r22d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r23d,[ebp-12] ; Use a help register
|
|
|
- add r20d,[r21d+4*r23d] ; Replace register by helpregister }
|
|
|
- subreg:=getsubreg(oper[i]^.ref^.index);
|
|
|
- if i=1 then
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),
|
|
|
- getsupreg(oper[0]^.reg),RS_INVALID)
|
|
|
- else
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID);
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- oper[i]^.ref^.index:=helpreg;
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- end;
|
|
|
- end;
|
|
|
- if (oper[0]^.typ=top_reg) and
|
|
|
- (getregtype(oper[0]^.reg)=regtype) then
|
|
|
- begin
|
|
|
- supreg:=getsupreg(oper[0]^.reg);
|
|
|
- subreg:=getsubreg(oper[0]^.reg);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- if oper[1]^.typ=top_ref then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- add [r20d],r21d ; r21d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r22d,[ebp-12] ; Use a help register
|
|
|
- add [r20d],r22d ; Replace register by helpregister }
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),
|
|
|
- getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index));
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- oper[0]^.reg:=helpreg;
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- add r20d,r21d ; r21d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- add r20d,[ebp-12] ; Replace register by reference }
|
|
|
- oper[0]^.typ:=top_ref;
|
|
|
- new(oper[0]^.ref);
|
|
|
- oper[0]^.ref^:=spilltemplist[supreg];
|
|
|
- end;
|
|
|
- end;
|
|
|
- if (oper[1]^.typ=top_reg) and
|
|
|
- (getregtype(oper[1]^.reg)=regtype) then
|
|
|
- begin
|
|
|
- supreg:=getsupreg(oper[1]^.reg);
|
|
|
- subreg:=getsubreg(oper[1]^.reg);
|
|
|
- if supregset_in(r,supreg) then
|
|
|
- begin
|
|
|
- if oper[0]^.typ=top_ref then
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- add r20d,[r21d] ; r20d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r22d,[r21d] ; Use a help register
|
|
|
- add [ebp-12],r22d ; Replace register by helpregister }
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),
|
|
|
- getsupreg(oper[0]^.ref^.index),RS_INVALID);
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- op:=A_MOV;
|
|
|
- hopsize:=opsize; {Save old value...}
|
|
|
- if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
|
|
|
- begin
|
|
|
- {Because 'movzx memory,register' does not exist...}
|
|
|
- op:=opcode;
|
|
|
- opcode:=A_MOV;
|
|
|
- opsize:=reg2opsize(oper[1]^.reg);
|
|
|
- end;
|
|
|
- helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- dispose(oper[0]^.ref);
|
|
|
- oper[0]^.typ:=top_reg;
|
|
|
- oper[0]^.reg:=helpreg;
|
|
|
- oper[1]^.typ:=top_ref;
|
|
|
- new(oper[1]^.ref);
|
|
|
- oper[1]^.ref^:=spilltemplist[supreg];
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- {Situation example:
|
|
|
- add r20d,r21d ; r20d must be spilled into [ebp-12]
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- add [ebp-12],r21d ; Replace register by reference }
|
|
|
- if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
|
|
|
- begin
|
|
|
- {Because 'movzx memory,register' does not exist...}
|
|
|
- result:=true;
|
|
|
- op:=opcode;
|
|
|
- hopsize:=opsize;
|
|
|
- opcode:=A_MOV;
|
|
|
- opsize:=reg2opsize(oper[1]^.reg);
|
|
|
- pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID);
|
|
|
- getregisterinline(list,pos,subreg,helpreg);
|
|
|
- helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
|
|
|
- if pos=nil then
|
|
|
- list.insertafter(helpins,list.first)
|
|
|
- else
|
|
|
- list.insertafter(helpins,pos.next);
|
|
|
- oper[0]^.reg:=helpreg;
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- forward_allocation(Tai(helpins.next),instr);
|
|
|
- end;
|
|
|
- oper[1]^.typ:=top_ref;
|
|
|
- new(oper[1]^.ref);
|
|
|
- oper[1]^.ref^:=spilltemplist[supreg];
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- { The i386 instruction set never gets boring...
|
|
|
- some opcodes do not support a memory location as destination }
|
|
|
- if (oper[1]^.typ=top_ref) and
|
|
|
- (
|
|
|
- (oper[0]^.typ=top_const) or
|
|
|
- ((oper[0]^.typ=top_reg) and
|
|
|
- (getregtype(oper[0]^.reg)=regtype))
|
|
|
- ) then
|
|
|
- begin
|
|
|
- case opcode of
|
|
|
- A_SHLD,A_SHRD,
|
|
|
- A_IMUL :
|
|
|
- begin
|
|
|
- {Yikes! We just changed the destination register into
|
|
|
- a memory location above here.
|
|
|
-
|
|
|
- Situation examples:
|
|
|
-
|
|
|
- imul [ebp-12],r21d ; We need a help register
|
|
|
- imul [ebp-12],<const> ; We need a help register
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
|
|
|
- imul r22d,r21d ; Replace reference by helpregister
|
|
|
- mov [ebp-12],r22d ; Use another help instruction}
|
|
|
- getregisterinline(list,Tai(previous),subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- {First help instruction.}
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
|
|
|
- if previous=nil then
|
|
|
- list.insert(helpins)
|
|
|
- else
|
|
|
- list.insertafter(helpins,previous);
|
|
|
- {Second help instruction.}
|
|
|
- helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
|
|
|
- dispose(oper[1]^.ref);
|
|
|
- oper[1]^.typ:=top_reg;
|
|
|
- oper[1]^.reg:=helpreg;
|
|
|
- list.insertafter(helpins,instr);
|
|
|
- ungetregisterinline(list,instr,helpreg);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- { The i386 instruction set never gets boring...
|
|
|
- some opcodes do not support a memory location as source }
|
|
|
- if (oper[0]^.typ=top_ref) and
|
|
|
- (oper[1]^.typ=top_reg) and
|
|
|
- (getregtype(oper[1]^.reg)=regtype) then
|
|
|
- begin
|
|
|
- case opcode of
|
|
|
- A_BT,A_BTS,
|
|
|
- A_BTC,A_BTR :
|
|
|
- begin
|
|
|
- {Yikes! We just changed the source register into
|
|
|
- a memory location above here.
|
|
|
-
|
|
|
- Situation example:
|
|
|
-
|
|
|
- bt r21d,[ebp-12] ; We need a help register
|
|
|
-
|
|
|
- Change into:
|
|
|
-
|
|
|
- mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
|
|
|
- bt r21d,r22d ; Replace reference by helpregister}
|
|
|
- getregisterinline(list,Tai(previous),subreg,helpreg);
|
|
|
- result:=true;
|
|
|
- {First help instruction.}
|
|
|
- helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
|
|
|
- if previous=nil then
|
|
|
- list.insert(helpins)
|
|
|
- else
|
|
|
- list.insertafter(helpins,previous);
|
|
|
- dispose(oper[0]^.ref);
|
|
|
- oper[0]^.typ:=top_reg;
|
|
|
- oper[0]^.reg:=helpreg;
|
|
|
- ungetregisterinline(list,helpins,helpreg);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
- else
|
|
|
- internalerror(200409202);
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
-{$endif OLDRGX86}
|
|
|
-
|
|
|
-
|
|
|
function trgx86.get_spill_subreg(r : tregister) : tsubregister;
|
|
|
begin
|
|
|
result:=getsubreg(r);
|
|
@@ -494,8 +112,80 @@ implementation
|
|
|
|
|
|
|
|
|
function trgx86.do_spill_replace(list:Taasmoutput;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
|
|
|
+ var
|
|
|
+ replaceoper : longint;
|
|
|
begin
|
|
|
result:=false;
|
|
|
+ with instr do
|
|
|
+ begin
|
|
|
+ replaceoper:=-1;
|
|
|
+ case ops of
|
|
|
+ 1 :
|
|
|
+ begin
|
|
|
+ if (oper[0]^.typ=top_reg) then
|
|
|
+ begin
|
|
|
+ if getsupreg(oper[0]^.reg)<>orgreg then
|
|
|
+ internalerror(200410101);
|
|
|
+ replaceoper:=0;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ 2,3 :
|
|
|
+ begin
|
|
|
+ { We can handle opcodes with 2 and 3 operands the same way. The opcodes
|
|
|
+ with 3 registers are shrd/shld, where the 3rd operand is const or CL,
|
|
|
+ that doesn't need spilling }
|
|
|
+ if (oper[0]^.typ=top_reg) and
|
|
|
+ (oper[1]^.typ=top_reg) and
|
|
|
+ (getsupreg(oper[0]^.reg)<>getsupreg(oper[1]^.reg)) then
|
|
|
+ begin
|
|
|
+ { One of the arguments shall be able to be replaced }
|
|
|
+ if (getregtype(oper[0]^.reg)=regtype) and
|
|
|
+ (getsupreg(oper[0]^.reg)=orgreg) then
|
|
|
+ replaceoper:=0
|
|
|
+ else
|
|
|
+ if (getregtype(oper[0]^.reg)=regtype) and
|
|
|
+ (getsupreg(oper[1]^.reg)=orgreg) then
|
|
|
+ replaceoper:=1
|
|
|
+ else
|
|
|
+ internalerror(200410101);
|
|
|
+ case replaceoper of
|
|
|
+ 0 :
|
|
|
+ begin
|
|
|
+ { Some instructions don't allow memory references
|
|
|
+ for source }
|
|
|
+ case instr.opcode of
|
|
|
+ A_BT,
|
|
|
+ A_BTS,
|
|
|
+ A_BTC,
|
|
|
+ A_BTR :
|
|
|
+ replaceoper:=-1;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ 1 :
|
|
|
+ begin
|
|
|
+ { Some instructions don't allow memory references
|
|
|
+ for destination }
|
|
|
+ case instr.opcode of
|
|
|
+ A_SHLD,
|
|
|
+ A_SHRD,
|
|
|
+ A_IMUL :
|
|
|
+ replaceoper:=-1;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { Replace register with spill reference }
|
|
|
+ if replaceoper<>-1 then
|
|
|
+ begin
|
|
|
+ oper[replaceoper]^.typ:=top_ref;
|
|
|
+ new(oper[replaceoper]^.ref);
|
|
|
+ oper[replaceoper]^.ref^:=spilltemp;
|
|
|
+ result:=true;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
|
|
@@ -625,7 +315,11 @@ implementation
|
|
|
end.
|
|
|
{
|
|
|
$Log$
|
|
|
- Revision 1.8 2004-10-05 20:41:02 peter
|
|
|
+ Revision 1.9 2004-10-10 16:30:26 peter
|
|
|
+ * optimized spilling writing when the reg operand can be
|
|
|
+ replaced by reference
|
|
|
+
|
|
|
+ Revision 1.8 2004/10/05 20:41:02 peter
|
|
|
* more spilling rewrites
|
|
|
|
|
|
Revision 1.7 2004/10/04 20:46:22 peter
|