mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 08:59:26 +02:00
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs to be added. * Spilling fixed when both operands needed to be spilled * Cleanup of spilling routine, do_spill_readwritten removed
This commit is contained in:
parent
ec720a5800
commit
ee3585f56f
@ -140,7 +140,7 @@ begin
|
||||
end
|
||||
end;
|
||||
else
|
||||
for opCount := 1 to MaxCh do
|
||||
for opCount := 1 to maxinschanges do
|
||||
case InsProp[p.opcode].Ch[opCount] of
|
||||
Ch_MOp1,CH_WOp1,CH_RWOp1:
|
||||
if not(onlymem) or
|
||||
@ -904,7 +904,7 @@ begin
|
||||
begin
|
||||
NoHardCodedRegs := true;
|
||||
with InsProp[p.opcode] do
|
||||
for chCount := 1 to MaxCh do
|
||||
for chCount := 1 to maxinschanges do
|
||||
if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
|
||||
begin
|
||||
NoHardCodedRegs := false;
|
||||
@ -1058,7 +1058,7 @@ begin
|
||||
{ updateStates(orgReg,newReg,p,false);}
|
||||
doReplaceReadReg := true;
|
||||
end;
|
||||
for opCount := 1 to MaxCh do
|
||||
for opCount := 1 to maxinschanges do
|
||||
case InsProp[p.opcode].Ch[opCount] of
|
||||
Ch_ROp1:
|
||||
if p.oper[0]^.typ = top_reg then
|
||||
@ -1901,7 +1901,7 @@ begin
|
||||
ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
|
||||
else
|
||||
begin
|
||||
for cnt := 1 to maxch do
|
||||
for cnt := 1 to maxinschanges do
|
||||
begin
|
||||
case InsProp[taicpu(p).opcode].Ch[cnt] of
|
||||
Ch_ROp1:
|
||||
@ -2109,7 +2109,14 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.65 2004-09-21 17:25:12 peter
|
||||
Revision 1.66 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.65 2004/09/21 17:25:12 peter
|
||||
* paraloc branch merged
|
||||
|
||||
Revision 1.64.4.1 2004/09/20 19:28:23 peter
|
||||
|
@ -725,7 +725,7 @@ begin
|
||||
RegReadByInstruction := true;
|
||||
exit
|
||||
end;
|
||||
for opcount := 1 to maxch do
|
||||
for opcount := 1 to maxinschanges do
|
||||
case insprop[p.opcode].ch[opcount] of
|
||||
CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI:
|
||||
if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then
|
||||
@ -791,7 +791,7 @@ begin
|
||||
(supreg in [RS_EAX,RS_EDX])
|
||||
else
|
||||
begin
|
||||
for opcount := 1 to MaxCh do
|
||||
for opcount := 1 to maxinschanges do
|
||||
case insprop[p.opcode].Ch[opCount] of
|
||||
CH_REAX..CH_MEDI:
|
||||
if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then
|
||||
@ -866,7 +866,7 @@ begin
|
||||
begin
|
||||
Cnt := 1;
|
||||
InstrProp := InsProp[taicpu(p1).OpCode];
|
||||
while (Cnt <= MaxCh) and
|
||||
while (Cnt <= maxinschanges) and
|
||||
(InstrProp.Ch[Cnt] <> Ch_None) and
|
||||
not(TmpResult) Do
|
||||
begin
|
||||
@ -901,7 +901,7 @@ begin
|
||||
case p.typ of
|
||||
ait_instruction:
|
||||
begin
|
||||
for l := 1 to MaxCh do
|
||||
for l := 1 to maxinschanges do
|
||||
if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then
|
||||
exit;
|
||||
end;
|
||||
@ -920,7 +920,7 @@ begin
|
||||
case p.typ of
|
||||
ait_instruction:
|
||||
begin
|
||||
for l := 1 to MaxCh do
|
||||
for l := 1 to maxinschanges do
|
||||
if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then
|
||||
exit;
|
||||
end;
|
||||
@ -2555,7 +2555,7 @@ begin
|
||||
else
|
||||
begin
|
||||
Cnt := 1;
|
||||
while (Cnt <= MaxCh) and
|
||||
while (Cnt <= maxinschanges) and
|
||||
(InstrProp.Ch[Cnt] <> Ch_None) Do
|
||||
begin
|
||||
case InstrProp.Ch[Cnt] Of
|
||||
@ -2719,7 +2719,14 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.69 2004-09-26 17:45:30 peter
|
||||
Revision 1.70 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.69 2004/09/26 17:45:30 peter
|
||||
* simple regvar support, not yet finished
|
||||
|
||||
Revision 1.68 2004/06/20 08:55:31 florian
|
||||
|
@ -28,49 +28,6 @@ unit optbase;
|
||||
|
||||
interface
|
||||
|
||||
uses cpuinfo, cpubase;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
Opcode propeties (needed for optimizer)
|
||||
*****************************************************************************}
|
||||
|
||||
{$ifndef NOOPT}
|
||||
Type
|
||||
{What an instruction can change}
|
||||
TInsChange = (Ch_None,
|
||||
{Read from a register}
|
||||
Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
|
||||
{write from a register}
|
||||
Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
|
||||
{read and write from/to a register}
|
||||
Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
|
||||
{modify the contents of a register with the purpose of using
|
||||
this changed content afterwards (add/sub/..., but e.g. not rep
|
||||
or movsd)}
|
||||
Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
|
||||
Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
|
||||
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
|
||||
Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
|
||||
Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
|
||||
Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
|
||||
Ch_WMemEDI,
|
||||
Ch_All
|
||||
);
|
||||
|
||||
|
||||
const
|
||||
MaxCh = 3; { Max things a instruction can change }
|
||||
type
|
||||
TInsProp = packed record
|
||||
Ch : Array[1..MaxCh] of TInsChange;
|
||||
end;
|
||||
|
||||
const
|
||||
InsProp : array[tasmop] of TInsProp =
|
||||
{$i i386prop.inc}
|
||||
|
||||
{$endif NOOPT}
|
||||
|
||||
implementation
|
||||
|
||||
@ -79,7 +36,14 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.3 2004-06-20 08:55:31 florian
|
||||
Revision 1.4 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.3 2004/06/20 08:55:31 florian
|
||||
* logs truncated
|
||||
|
||||
}
|
||||
|
@ -135,8 +135,6 @@ unit rgobj;
|
||||
trgobj=class
|
||||
preserved_by_proc : tcpuregisterset;
|
||||
used_in_proc : tcpuregisterset;
|
||||
// is_reg_var : Tsuperregisterset; {old regvars}
|
||||
// reg_var_loaded:Tsuperregisterset; {old regvars}
|
||||
|
||||
constructor create(Aregtype:Tregistertype;
|
||||
Adefaultsub:Tsubregister;
|
||||
@ -170,25 +168,12 @@ unit rgobj;
|
||||
live_registers:Tsuperregisterworklist;
|
||||
{ can be overriden to add cpu specific interferences }
|
||||
procedure add_cpu_interferences(p : tai);virtual;
|
||||
function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
|
||||
procedure forward_allocation(pfrom,pto:Tai);
|
||||
procedure add_constraints(reg:Tregister);virtual;
|
||||
procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
|
||||
procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
|
||||
procedure add_constraints(reg:Tregister);virtual;
|
||||
|
||||
function get_spill_subreg(r : tregister) : tsubregister;virtual;
|
||||
procedure do_spill_read(list:Taasmoutput;instr:Taicpu;
|
||||
pos:Tai;regidx:word;
|
||||
const spilltemplist:Tspill_temp_list;
|
||||
const regs:Tspillregsinfo);virtual;
|
||||
procedure do_spill_written(list:Taasmoutput;instr:Taicpu;
|
||||
pos:Tai;regidx:word;
|
||||
const spilltemplist:Tspill_temp_list;
|
||||
const regs:Tspillregsinfo);virtual;
|
||||
procedure do_spill_readwritten(list:Taasmoutput;instr:Taicpu;
|
||||
pos:Tai;regidx:word;
|
||||
const spilltemplist:Tspill_temp_list;
|
||||
const regs:Tspillregsinfo);virtual;
|
||||
procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual;
|
||||
procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual;
|
||||
|
||||
function instr_spill_register(list:Taasmoutput;
|
||||
instr:taicpu;
|
||||
@ -603,22 +588,12 @@ unit rgobj;
|
||||
procedure trgobj.add_edges_used(u:Tsuperregister);
|
||||
|
||||
var i:word;
|
||||
v:tsuperregister;
|
||||
|
||||
begin
|
||||
with live_registers do
|
||||
if length>0 then
|
||||
for i:=0 to length-1 do
|
||||
begin
|
||||
v:=buf^[i];
|
||||
add_edge(u,v);
|
||||
{ add also conflicts with all coalesced registers }
|
||||
while ri_coalesced in reginfo[v].flags do
|
||||
begin
|
||||
v:=reginfo[v].alias;
|
||||
add_edge(u,v);
|
||||
end;
|
||||
end;
|
||||
add_edge(u,get_alias(buf^[i]));
|
||||
end;
|
||||
|
||||
{$ifdef EXTDEBUG}
|
||||
@ -1638,69 +1613,6 @@ unit rgobj;
|
||||
end;
|
||||
|
||||
|
||||
function trgobj.get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
|
||||
var
|
||||
back : Tsuperregisterworklist;
|
||||
supreg : tsuperregister;
|
||||
begin
|
||||
back.copyfrom(live_registers);
|
||||
result:=p;
|
||||
while (p<>nil) and (p.typ=ait_regalloc) do
|
||||
begin
|
||||
supreg:=getsupreg(Tai_regalloc(p).reg);
|
||||
{Rewind the register allocation.}
|
||||
if (Tai_regalloc(p).ratype=ra_alloc) then
|
||||
live_registers.delete(supreg)
|
||||
else
|
||||
begin
|
||||
live_registers.add(supreg);
|
||||
if supreg=huntfor1 then
|
||||
begin
|
||||
get_insert_pos:=Tai(p.previous);
|
||||
back.done;
|
||||
back.copyfrom(live_registers);
|
||||
end;
|
||||
if supreg=huntfor2 then
|
||||
begin
|
||||
get_insert_pos:=Tai(p.previous);
|
||||
back.done;
|
||||
back.copyfrom(live_registers);
|
||||
end;
|
||||
if supreg=huntfor3 then
|
||||
begin
|
||||
get_insert_pos:=Tai(p.previous);
|
||||
back.done;
|
||||
back.copyfrom(live_registers);
|
||||
end;
|
||||
end;
|
||||
p:=Tai(p.previous);
|
||||
end;
|
||||
live_registers.done;
|
||||
live_registers:=back;
|
||||
end;
|
||||
|
||||
|
||||
procedure trgobj.forward_allocation(pfrom,pto:Tai);
|
||||
var
|
||||
p : tai;
|
||||
begin
|
||||
{Forward the register allocation again.}
|
||||
p:=pfrom;
|
||||
while (p<>pto) do
|
||||
begin
|
||||
if p.typ<>ait_regalloc then
|
||||
internalerror(200305311);
|
||||
case Tai_regalloc(p).ratype of
|
||||
ra_alloc :
|
||||
live_registers.add(getsupreg(Tai_regalloc(p).reg));
|
||||
ra_dealloc :
|
||||
live_registers.delete(getsupreg(Tai_regalloc(p).reg));
|
||||
end;
|
||||
p:=Tai(p.next);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
|
||||
{ Returns true if any help registers have been used }
|
||||
var
|
||||
@ -1790,65 +1702,22 @@ unit rgobj;
|
||||
end;
|
||||
|
||||
|
||||
procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu;
|
||||
pos:Tai;regidx:word;
|
||||
const spilltemplist:Tspill_temp_list;
|
||||
const regs:Tspillregsinfo);
|
||||
|
||||
var helpins:Tai;
|
||||
|
||||
begin
|
||||
with regs[regidx] do
|
||||
begin
|
||||
helpins:=spilling_create_load(spilltemplist[orgreg],tempreg);
|
||||
if pos=nil then
|
||||
list.insertafter(helpins,list.first)
|
||||
else
|
||||
list.insertafter(helpins,pos.next);
|
||||
ungetregisterinline(list,instr,tempreg);
|
||||
forward_allocation(tai(helpins.next),instr);
|
||||
end;
|
||||
end;
|
||||
procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
|
||||
var
|
||||
helpins : Tai;
|
||||
begin
|
||||
helpins:=spilling_create_load(spilltemp,tempreg);
|
||||
list.insertbefore(helpins,instr);
|
||||
end;
|
||||
|
||||
|
||||
procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu;
|
||||
pos:Tai;regidx:word;
|
||||
const spilltemplist:Tspill_temp_list;
|
||||
const regs:Tspillregsinfo);
|
||||
|
||||
var helpins:Tai;
|
||||
|
||||
begin
|
||||
with regs[regidx] do
|
||||
begin
|
||||
helpins:=spilling_create_store(tempreg,spilltemplist[orgreg]);
|
||||
list.insertafter(helpins,instr);
|
||||
ungetregisterinline(list,helpins,tempreg);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure Trgobj.do_spill_readwritten(list:Taasmoutput;instr:taicpu;
|
||||
pos:Tai;regidx:word;
|
||||
const spilltemplist:Tspill_temp_list;
|
||||
const regs:Tspillregsinfo);
|
||||
|
||||
var helpins1,helpins2:Tai;
|
||||
|
||||
begin
|
||||
with regs[regidx] do
|
||||
begin
|
||||
helpins1:=spilling_create_load(spilltemplist[orgreg],tempreg);
|
||||
if pos=nil then
|
||||
list.insertafter(helpins1,list.first)
|
||||
else
|
||||
list.insertafter(helpins1,pos.next);
|
||||
helpins2:=spilling_create_store(tempreg,spilltemplist[orgreg]);
|
||||
list.insertafter(helpins2,instr);
|
||||
ungetregisterinline(list,helpins2,tempreg);
|
||||
forward_allocation(tai(helpins1.next),instr);
|
||||
end;
|
||||
end;
|
||||
procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
|
||||
var
|
||||
helpins : Tai;
|
||||
begin
|
||||
helpins:=spilling_create_store(tempreg,spilltemp);
|
||||
list.insertafter(helpins,instr);
|
||||
end;
|
||||
|
||||
|
||||
function trgobj.get_spill_subreg(r : tregister) : tsubregister;
|
||||
@ -1863,7 +1732,6 @@ unit rgobj;
|
||||
const spilltemplist:Tspill_temp_list): boolean;
|
||||
var
|
||||
counter, regindex: longint;
|
||||
pos: tai;
|
||||
regs: tspillregsinfo;
|
||||
spilled: boolean;
|
||||
|
||||
@ -1874,7 +1742,7 @@ unit rgobj;
|
||||
begin
|
||||
tmpindex := regindex;
|
||||
supreg:=getsupreg(reg);
|
||||
// did we already encounter this register?
|
||||
{ did we already encounter this register? }
|
||||
for i := 0 to pred(regindex) do
|
||||
if (regs[i].orgreg = supreg) then
|
||||
begin
|
||||
@ -1887,7 +1755,7 @@ unit rgobj;
|
||||
regs[tmpindex].spillreg:=reg;
|
||||
if supregset_in(r,supreg) then
|
||||
begin
|
||||
// add/update info on this register
|
||||
{ add/update info on this register }
|
||||
regs[tmpindex].mustbespilled := true;
|
||||
case operation of
|
||||
operand_read:
|
||||
@ -1916,12 +1784,15 @@ unit rgobj;
|
||||
if (regs[i].mustbespilled) and
|
||||
(regs[i].orgreg=supreg) then
|
||||
begin
|
||||
reg:=regs[i].tempreg;
|
||||
{ Only replace supreg }
|
||||
setsupreg(reg,getsupreg(regs[i].tempreg));
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
counter2 : longint;
|
||||
oldlive_registers : tsuperregisterworklist;
|
||||
begin
|
||||
result := false;
|
||||
fillchar(regs,sizeof(regs),0);
|
||||
@ -1966,6 +1837,14 @@ unit rgobj;
|
||||
if not spilled then
|
||||
exit;
|
||||
|
||||
{ Add conflicts with all non-spilled registers }
|
||||
oldlive_registers.copyfrom(live_registers);
|
||||
for counter2 := 0 to pred(regindex) do
|
||||
begin
|
||||
if (not regs[counter2].mustbespilled) then
|
||||
live_registers.add(get_alias(regs[counter2].orgreg));
|
||||
end;
|
||||
|
||||
{ generate the spilling code }
|
||||
result := true;
|
||||
for counter := 0 to pred(regindex) do
|
||||
@ -1973,18 +1852,27 @@ unit rgobj;
|
||||
begin
|
||||
if mustbespilled then
|
||||
begin
|
||||
pos:=get_insert_pos(Tai(instr.previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg);
|
||||
getregisterinline(list,pos,get_spill_subreg(regs[counter].spillreg),tempreg);
|
||||
getregisterinline(list,tai(instr.previous),get_spill_subreg(regs[counter].spillreg),tempreg);
|
||||
|
||||
if regread then
|
||||
if regwritten then
|
||||
do_spill_readwritten(list,instr,pos,counter,spilltemplist,regs)
|
||||
else
|
||||
do_spill_read(list,instr,pos,counter,spilltemplist,regs)
|
||||
else
|
||||
do_spill_written(list,instr,pos,counter,spilltemplist,regs)
|
||||
do_spill_read(list,instr,spilltemplist[orgreg],tempreg);
|
||||
if regwritten then
|
||||
do_spill_written(list,instr,spilltemplist[orgreg],tempreg);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Release temp registers after all registers for the instruction are spilled }
|
||||
for counter := 0 to pred(regindex) do
|
||||
with regs[counter] do
|
||||
begin
|
||||
if mustbespilled then
|
||||
ungetregisterinline(list,instr,tempreg);
|
||||
end;
|
||||
|
||||
{ restore live registers }
|
||||
live_registers.done;
|
||||
live_registers:=oldlive_registers;
|
||||
|
||||
{ substitute registers }
|
||||
for counter:=0 to instr.ops-1 do
|
||||
with instr.oper[counter]^ do
|
||||
@ -2015,7 +1903,14 @@ unit rgobj;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.137 2004-09-26 17:45:30 peter
|
||||
Revision 1.138 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.137 2004/09/26 17:45:30 peter
|
||||
* simple regvar support, not yet finished
|
||||
|
||||
Revision 1.136 2004/09/25 14:23:54 peter
|
||||
|
@ -36,12 +36,8 @@ unit rgcpu;
|
||||
trgcpu=class(trgobj)
|
||||
procedure add_constraints(reg:tregister);override;
|
||||
function get_spill_subreg(r : tregister) : tsubregister;override;
|
||||
procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
|
||||
procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
|
||||
procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
|
||||
procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override;
|
||||
procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override;
|
||||
end;
|
||||
|
||||
|
||||
@ -91,159 +87,89 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
|
||||
procedure trgcpu.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
|
||||
var
|
||||
helpins: tai;
|
||||
tmpref,ref : treference;
|
||||
helpins : tai;
|
||||
tmpref : treference;
|
||||
helplist : taasmoutput;
|
||||
tmpreg : tregister;
|
||||
hreg : tregister;
|
||||
begin
|
||||
ref:=spilltemplist[regs[regidx].orgreg];
|
||||
if abs(ref.offset)>4095 then
|
||||
if abs(spilltemp.offset)>4095 then
|
||||
begin
|
||||
helplist:=taasmoutput.create;
|
||||
reference_reset(tmpref);
|
||||
|
||||
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
|
||||
getregisterinline(helplist,nil,defaultsub,tmpreg)
|
||||
if getregtype(tempreg)=R_INTREGISTER then
|
||||
hreg:=tempreg
|
||||
else
|
||||
tmpreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
hreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
|
||||
tmpref.offset:=ref.offset;
|
||||
reference_reset(tmpref);
|
||||
tmpref.offset:=spilltemp.offset;
|
||||
tmpref.refaddr:=addr_hi;
|
||||
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
|
||||
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
|
||||
|
||||
tmpref.refaddr:=addr_lo;
|
||||
helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
|
||||
helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
|
||||
|
||||
if ref.index<>NR_NO then
|
||||
internalerror(200401263);
|
||||
ref.index:=tmpreg;
|
||||
ref.offset:=0;
|
||||
reference_reset_base(tmpref,hreg,0);
|
||||
|
||||
helpins:=spilling_create_load(ref,regs[regidx].tempreg);
|
||||
helpins:=spilling_create_load(spilltemp,tempreg);
|
||||
helplist.concat(helpins);
|
||||
if pos=nil then
|
||||
list.insertlistafter(list.first,helplist)
|
||||
else
|
||||
list.insertlistafter(pos.next,helplist);
|
||||
helplist.free;
|
||||
|
||||
ungetregisterinline(list,helpins,regs[regidx].tempreg);
|
||||
|
||||
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
|
||||
ungetregisterinline(list,helpins,tmpreg);
|
||||
|
||||
forward_allocation(tai(helpins.next),instr);
|
||||
list.insertlistbefore(instr,helplist)
|
||||
end
|
||||
else
|
||||
inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs);
|
||||
inherited do_spill_read(list,instr,spilltemp,tempreg);
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
|
||||
procedure trgcpu.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
|
||||
var
|
||||
helpins: tai;
|
||||
ref,tmpref : treference;
|
||||
helpins : tai;
|
||||
tmpref : treference;
|
||||
helplist : taasmoutput;
|
||||
tmpreg : tregister;
|
||||
hreg : tregister;
|
||||
begin
|
||||
ref:=spilltemplist[regs[regidx].orgreg];
|
||||
if abs(ref.offset)>4095 then
|
||||
if abs(spilltemp.offset)>4095 then
|
||||
begin
|
||||
helplist:=taasmoutput.create;
|
||||
reference_reset(tmpref);
|
||||
|
||||
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
|
||||
getregisterinline(helplist,pos,defaultsub,tmpreg)
|
||||
if getregtype(tempreg)=R_INTREGISTER then
|
||||
getregisterinline(helplist,tai(helplist.first),R_SUBWHOLE,hreg)
|
||||
else
|
||||
tmpreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
hreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
|
||||
tmpref.offset:=ref.offset;
|
||||
reference_reset(tmpref);
|
||||
tmpref.offset:=spilltemp.offset;
|
||||
tmpref.refaddr:=addr_hi;
|
||||
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
|
||||
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
|
||||
|
||||
tmpref.refaddr:=addr_lo;
|
||||
helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
|
||||
helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
|
||||
|
||||
if ref.index<>NR_NO then
|
||||
internalerror(200401263);
|
||||
ref.index:=tmpreg;
|
||||
ref.offset:=0;
|
||||
reference_reset_base(tmpref,hreg,0);
|
||||
|
||||
helpins:=spilling_create_store(regs[regidx].tempreg,ref);
|
||||
helpins:=spilling_create_store(tempreg,spilltemp);
|
||||
helplist.concat(helpins);
|
||||
list.insertlistafter(instr,helplist);
|
||||
helplist.free;
|
||||
if getregtype(tempreg)=R_INTREGISTER then
|
||||
ungetregisterinline(helplist,tai(helplist.last),hreg);
|
||||
|
||||
ungetregisterinline(list,helpins,regs[regidx].tempreg);
|
||||
|
||||
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
|
||||
ungetregisterinline(list,helpins,tmpreg);
|
||||
list.insertlistafter(instr,helplist)
|
||||
end
|
||||
else
|
||||
inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs);
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
|
||||
var
|
||||
helpins1, helpins2: tai;
|
||||
tmpref,ref : treference;
|
||||
helplist : taasmoutput;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
ref:=spilltemplist[regs[regidx].orgreg];
|
||||
if abs(ref.offset)>4095 then
|
||||
begin
|
||||
helplist:=taasmoutput.create;
|
||||
reference_reset(tmpref);
|
||||
|
||||
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
|
||||
getregisterinline(helplist,nil,defaultsub,tmpreg)
|
||||
else
|
||||
tmpreg:=cg.getintregister(helplist,OS_ADDR);
|
||||
|
||||
tmpref.offset:=ref.offset;
|
||||
tmpref.refaddr:=addr_hi;
|
||||
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
|
||||
|
||||
tmpref.refaddr:=addr_lo;
|
||||
helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
|
||||
|
||||
if ref.index<>NR_NO then
|
||||
internalerror(200401263);
|
||||
ref.index:=tmpreg;
|
||||
ref.offset:=0;
|
||||
|
||||
helpins1:=spilling_create_load(ref,regs[regidx].tempreg);
|
||||
helplist.concat(helpins1);
|
||||
if pos=nil then
|
||||
list.insertlistafter(list.first,helplist)
|
||||
else
|
||||
list.insertlistafter(pos.next,helplist);
|
||||
helplist.free;
|
||||
|
||||
helpins2:=spilling_create_store(regs[regidx].tempreg,ref);
|
||||
list.insertafter(helpins2,instr);
|
||||
ungetregisterinline(list,helpins2,regs[regidx].tempreg);
|
||||
|
||||
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
|
||||
ungetregisterinline(list,helpins2,tmpreg);
|
||||
|
||||
forward_allocation(tai(helpins1.next),instr);
|
||||
end
|
||||
else
|
||||
inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs);
|
||||
end;
|
||||
inherited do_spill_written(list,instr,spilltemp,tempreg);
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.27 2004-10-01 17:33:47 peter
|
||||
Revision 1.28 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.27 2004/10/01 17:33:47 peter
|
||||
* indents
|
||||
|
||||
Revision 1.26 2004/09/28 20:19:36 peter
|
||||
|
@ -130,6 +130,36 @@ interface
|
||||
instabentries = {$i i386nop.inc}
|
||||
{$endif x86_64}
|
||||
maxinfolen = 8;
|
||||
MaxInsChanges = 3; { Max things a instruction can change }
|
||||
|
||||
type
|
||||
{ What an instruction can change. Needed for optimizer and spilling code }
|
||||
TInsChange = (Ch_None,
|
||||
{Read from a register}
|
||||
Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
|
||||
{write from a register}
|
||||
Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
|
||||
{read and write from/to a register}
|
||||
Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
|
||||
{modify the contents of a register with the purpose of using
|
||||
this changed content afterwards (add/sub/..., but e.g. not rep
|
||||
or movsd)}
|
||||
Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
|
||||
Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
|
||||
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
|
||||
Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
|
||||
Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
|
||||
Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
|
||||
Ch_WMemEDI,
|
||||
Ch_All
|
||||
);
|
||||
|
||||
TInsProp = packed record
|
||||
Ch : Array[1..MaxInsChanges] of TInsChange;
|
||||
end;
|
||||
|
||||
const
|
||||
InsProp : array[tasmop] of TInsProp = {$i i386prop.inc}
|
||||
|
||||
type
|
||||
TOperandOrder = (op_intel,op_att);
|
||||
@ -201,6 +231,8 @@ interface
|
||||
procedure Pass2(objdata:TAsmObjectdata);virtual;
|
||||
procedure SetOperandOrder(order:TOperandOrder);
|
||||
function is_same_reg_move(regtype: Tregistertype):boolean;override;
|
||||
{ register spilling code }
|
||||
function spilling_get_operation_type(opnr: longint): topertype;override;
|
||||
protected
|
||||
procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
|
||||
procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
|
||||
@ -366,6 +398,12 @@ implementation
|
||||
);
|
||||
{$endif x86_64}
|
||||
|
||||
{ Operation type for spilling code }
|
||||
type
|
||||
toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
|
||||
var
|
||||
operation_type_table : ^toperation_type_table;
|
||||
|
||||
|
||||
{****************************************************************************
|
||||
TAI_ALIGN
|
||||
@ -1932,15 +1970,74 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure build_spilling_operation_type_table;
|
||||
var
|
||||
opcode : tasmop;
|
||||
i : integer;
|
||||
begin
|
||||
new(operation_type_table);
|
||||
fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
|
||||
for opcode:=low(tasmop) to high(tasmop) do
|
||||
begin
|
||||
for i:=1 to MaxInsChanges do
|
||||
begin
|
||||
case InsProp[opcode].Ch[i] of
|
||||
Ch_Rop1 :
|
||||
operation_type_table^[opcode,0]:=operand_read;
|
||||
Ch_Wop1 :
|
||||
operation_type_table^[opcode,0]:=operand_write;
|
||||
Ch_RWop1,
|
||||
Ch_Mop1 :
|
||||
operation_type_table^[opcode,0]:=operand_readwrite;
|
||||
Ch_Rop2 :
|
||||
operation_type_table^[opcode,1]:=operand_read;
|
||||
Ch_Wop2 :
|
||||
operation_type_table^[opcode,1]:=operand_write;
|
||||
Ch_RWop2,
|
||||
Ch_Mop2 :
|
||||
operation_type_table^[opcode,1]:=operand_readwrite;
|
||||
Ch_Rop3 :
|
||||
operation_type_table^[opcode,2]:=operand_read;
|
||||
Ch_Wop3 :
|
||||
operation_type_table^[opcode,2]:=operand_write;
|
||||
Ch_RWop3,
|
||||
Ch_Mop3 :
|
||||
operation_type_table^[opcode,2]:=operand_readwrite;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function taicpu.spilling_get_operation_type(opnr: longint): topertype;
|
||||
begin
|
||||
result:=operation_type_table^[opcode,opnr];
|
||||
end;
|
||||
|
||||
|
||||
function spilling_create_load(const ref:treference;r:tregister): tai;
|
||||
begin
|
||||
internalerror(200406131);
|
||||
case getregtype(r) of
|
||||
R_INTREGISTER :
|
||||
result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r);
|
||||
R_MMREGISTER :
|
||||
result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r);
|
||||
else
|
||||
internalerror(200401041);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function spilling_create_store(r:tregister; const ref:treference): tai;
|
||||
begin
|
||||
internalerror(200406132);
|
||||
case getregtype(r) of
|
||||
R_INTREGISTER :
|
||||
result:=taicpu.op_reg_ref(A_MOV,reg2opsize(r),r,ref);
|
||||
R_MMREGISTER :
|
||||
result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref);
|
||||
else
|
||||
internalerror(200401041);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -1970,6 +2067,7 @@ implementation
|
||||
|
||||
procedure InitAsm;
|
||||
begin
|
||||
build_spilling_operation_type_table;
|
||||
{$ifndef NOAG386BIN}
|
||||
if not assigned(instabcache) then
|
||||
BuildInsTabCache;
|
||||
@ -1979,12 +2077,17 @@ implementation
|
||||
|
||||
procedure DoneAsm;
|
||||
begin
|
||||
if assigned(operation_type_table) then
|
||||
begin
|
||||
dispose(operation_type_table);
|
||||
operation_type_table:=nil;
|
||||
end;
|
||||
{$ifndef NOAG386BIN}
|
||||
if assigned(instabcache) then
|
||||
begin
|
||||
dispose(instabcache);
|
||||
instabcache:=nil;
|
||||
end;
|
||||
begin
|
||||
dispose(instabcache);
|
||||
instabcache:=nil;
|
||||
end;
|
||||
{$endif NOAG386BIN}
|
||||
end;
|
||||
|
||||
@ -1995,7 +2098,14 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.58 2004-09-27 15:12:47 peter
|
||||
Revision 1.59 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.58 2004/09/27 15:12:47 peter
|
||||
* IE when expecting top_ref
|
||||
|
||||
Revision 1.57 2004/06/20 08:55:32 florian
|
||||
|
@ -551,11 +551,14 @@ unit cgx86;
|
||||
if s in [S_BL,S_WL,S_L] then
|
||||
reg2:=makeregsize(list,reg2,OS_32);
|
||||
{$endif x86_64}
|
||||
instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
|
||||
{ Notify the register allocator that we have written a move instruction so
|
||||
it can try to eliminate it. }
|
||||
add_move_instruction(instr);
|
||||
list.concat(instr);
|
||||
if (reg1<>reg2) then
|
||||
begin
|
||||
instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
|
||||
{ Notify the register allocator that we have written a move instruction so
|
||||
it can try to eliminate it. }
|
||||
add_move_instruction(instr);
|
||||
list.concat(instr);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
@ -1672,7 +1675,14 @@ unit cgx86;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.126 2004-10-03 12:42:22 florian
|
||||
Revision 1.127 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.126 2004/10/03 12:42:22 florian
|
||||
* made sqrt, sqr and abs internal for the sparc
|
||||
|
||||
Revision 1.125 2004/09/25 14:23:55 peter
|
||||
|
@ -36,10 +36,21 @@ unit rgx86;
|
||||
|
||||
type
|
||||
trgx86 = class(trgobj)
|
||||
{$ifdef OLDRGX86}
|
||||
function instr_spill_register(list:Taasmoutput;
|
||||
instr:taicpu;
|
||||
const r:Tsuperregisterset;
|
||||
const spilltemplist:Tspill_temp_list): boolean;override;
|
||||
{$endif OLDRGX86}
|
||||
function get_spill_subreg(r : tregister) : tsubregister;override;
|
||||
{
|
||||
procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
|
||||
procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
|
||||
procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
|
||||
}
|
||||
end;
|
||||
|
||||
tpushedsavedloc = record
|
||||
@ -107,6 +118,7 @@ implementation
|
||||
Trgcpu
|
||||
******************************************************************************}
|
||||
|
||||
{$ifdef OLDRGX86}
|
||||
function trgx86.instr_spill_register(list:Taasmoutput;
|
||||
instr:taicpu;
|
||||
const r:Tsuperregisterset;
|
||||
@ -485,8 +497,67 @@ implementation
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$endif OLDRGX86}
|
||||
|
||||
|
||||
function trgx86.get_spill_subreg(r : tregister) : tsubregister;
|
||||
begin
|
||||
result:=getsubreg(r);
|
||||
end;
|
||||
|
||||
|
||||
(*
|
||||
procedure trgx86.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
|
||||
var
|
||||
helpins: tai;
|
||||
tmpref,ref : treference;
|
||||
helplist : taasmoutput;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
{ ref:=spilltemplist[regs[regidx].orgreg];
|
||||
if abs(ref.offset)>4095 then
|
||||
begin
|
||||
end
|
||||
else }
|
||||
inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs);
|
||||
end;
|
||||
|
||||
|
||||
procedure trgx86.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
|
||||
var
|
||||
helpins: tai;
|
||||
ref,tmpref : treference;
|
||||
helplist : taasmoutput;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
{ ref:=spilltemplist[regs[regidx].orgreg];
|
||||
if abs(ref.offset)>4095 then
|
||||
begin
|
||||
end
|
||||
else }
|
||||
inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs);
|
||||
end;
|
||||
|
||||
|
||||
procedure trgx86.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
|
||||
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
|
||||
var
|
||||
helpins1, helpins2: tai;
|
||||
tmpref,ref : treference;
|
||||
helplist : taasmoutput;
|
||||
tmpreg : tregister;
|
||||
begin
|
||||
{ ref:=spilltemplist[regs[regidx].orgreg];
|
||||
if abs(ref.offset)>4095 then
|
||||
begin
|
||||
end
|
||||
else }
|
||||
inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs);
|
||||
end;
|
||||
*)
|
||||
|
||||
{******************************************************************************
|
||||
Trgx86fpu
|
||||
******************************************************************************}
|
||||
@ -619,7 +690,14 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.6 2004-09-27 14:49:45 peter
|
||||
Revision 1.7 2004-10-04 20:46:22 peter
|
||||
* spilling code rewritten for x86. It now used the generic
|
||||
spilling routines. Special x86 optimization still needs
|
||||
to be added.
|
||||
* Spilling fixed when both operands needed to be spilled
|
||||
* Cleanup of spilling routine, do_spill_readwritten removed
|
||||
|
||||
Revision 1.6 2004/09/27 14:49:45 peter
|
||||
* handle 3 operand opcodes the same as 2 operand opcodes, the
|
||||
third operand can only be a const or register CL, so it doesn't
|
||||
affect spilling
|
||||
|
Loading…
Reference in New Issue
Block a user