mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-20 17:29:57 +02:00
* remove some obsolete i386 specific code
* use a_optimize_const to remove useless opcodes git-svn-id: trunk@2910 -
This commit is contained in:
parent
2b9ccf6579
commit
588cccb3ca
@ -81,6 +81,7 @@ interface
|
|||||||
topcg =
|
topcg =
|
||||||
(
|
(
|
||||||
OP_NONE,
|
OP_NONE,
|
||||||
|
OP_MOVE, { replaced operation with direct load }
|
||||||
OP_ADD, { simple addition }
|
OP_ADD, { simple addition }
|
||||||
OP_AND, { simple logical and }
|
OP_AND, { simple logical and }
|
||||||
OP_DIV, { simple unsigned division }
|
OP_DIV, { simple unsigned division }
|
||||||
@ -593,7 +594,7 @@ implementation
|
|||||||
function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
|
function commutativeop(op: topcg): boolean;{$ifdef USEINLINE}inline;{$endif}
|
||||||
const
|
const
|
||||||
list: array[topcg] of boolean =
|
list: array[topcg] of boolean =
|
||||||
(true,true,true,false,false,true,true,false,false,
|
(true,false,true,true,false,false,true,true,false,false,
|
||||||
true,false,false,false,false,true);
|
true,false,false,false,false,true);
|
||||||
begin
|
begin
|
||||||
commutativeop := list[op];
|
commutativeop := list[op];
|
||||||
|
@ -285,18 +285,16 @@ unit cgobj;
|
|||||||
procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
|
procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref:TReference); virtual;
|
||||||
|
|
||||||
{
|
{
|
||||||
This routine tries to optimize the const_reg opcode, and should be
|
This routine tries to optimize the op_const_reg/ref opcode, and should be
|
||||||
called at the start of a_op_const_reg. It returns the actual opcode
|
called at the start of a_op_const_reg/ref. It returns the actual opcode
|
||||||
to emit, and the constant value to emit. If this routine returns
|
to emit, and the constant value to emit. This function can opcode OP_NONE to
|
||||||
TRUE, @var(no) instruction should be emitted (.eg : imul reg by 1 )
|
remove the opcode and OP_MOVE to replace it with a simple load
|
||||||
|
|
||||||
@param(op The opcode to emit, returns the opcode which must be emitted)
|
@param(op The opcode to emit, returns the opcode which must be emitted)
|
||||||
@param(a The constant which should be emitted, returns the constant which must
|
@param(a The constant which should be emitted, returns the constant which must
|
||||||
be emitted)
|
be emitted)
|
||||||
@param(reg The register to emit the opcode with, returns the register with
|
|
||||||
which the opcode will be emitted)
|
|
||||||
}
|
}
|
||||||
function optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aint; var reg: tregister): boolean;virtual;
|
procedure optimize_op_const(var op: topcg; var a : aint);virtual;
|
||||||
|
|
||||||
{#
|
{#
|
||||||
This routine is used in exception management nodes. It should
|
This routine is used in exception management nodes. It should
|
||||||
@ -936,55 +934,69 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tcg.optimize_op_const_reg(list: taasmoutput; var op: topcg; var a : aint; var reg:tregister): boolean;
|
procedure tcg.optimize_op_const(var op: topcg; var a : aint);
|
||||||
var
|
var
|
||||||
powerval : longint;
|
powerval : longint;
|
||||||
begin
|
begin
|
||||||
optimize_op_const_reg := false;
|
|
||||||
case op of
|
case op of
|
||||||
|
OP_OR :
|
||||||
|
begin
|
||||||
{ or with zero returns same result }
|
{ or with zero returns same result }
|
||||||
OP_OR : if a = 0 then optimize_op_const_reg := true;
|
if a = 0 then
|
||||||
|
op:=OP_NONE
|
||||||
|
else
|
||||||
|
{ or with max returns max }
|
||||||
|
if a = -1 then
|
||||||
|
op:=OP_MOVE;
|
||||||
|
end;
|
||||||
|
OP_AND :
|
||||||
|
begin
|
||||||
{ and with max returns same result }
|
{ and with max returns same result }
|
||||||
OP_AND : if (a = high(a)) then optimize_op_const_reg := true;
|
if (a = -1) then
|
||||||
{ division by 1 returns result }
|
op:=OP_NONE
|
||||||
|
else
|
||||||
|
{ and with 0 returns 0 }
|
||||||
|
if a=0 then
|
||||||
|
op:=OP_MOVE;
|
||||||
|
end;
|
||||||
OP_DIV :
|
OP_DIV :
|
||||||
begin
|
begin
|
||||||
|
{ division by 1 returns result }
|
||||||
if a = 1 then
|
if a = 1 then
|
||||||
optimize_op_const_reg := true
|
op:=OP_NONE
|
||||||
else if ispowerof2(int64(a), powerval) then
|
else if ispowerof2(int64(a), powerval) then
|
||||||
begin
|
begin
|
||||||
a := powerval;
|
a := powerval;
|
||||||
op:= OP_SHR;
|
op:= OP_SHR;
|
||||||
end;
|
end;
|
||||||
exit;
|
|
||||||
end;
|
end;
|
||||||
OP_IDIV:
|
OP_IDIV:
|
||||||
begin
|
begin
|
||||||
if a = 1 then
|
if a = 1 then
|
||||||
optimize_op_const_reg := true
|
op:=OP_NONE;
|
||||||
else if ispowerof2(int64(a), powerval) then
|
|
||||||
begin
|
|
||||||
a := powerval;
|
|
||||||
op:= OP_SAR;
|
|
||||||
end;
|
|
||||||
exit;
|
|
||||||
end;
|
end;
|
||||||
OP_MUL,OP_IMUL:
|
OP_MUL,OP_IMUL:
|
||||||
begin
|
begin
|
||||||
if a = 1 then
|
if a = 1 then
|
||||||
optimize_op_const_reg := true
|
op:=OP_NONE
|
||||||
|
else
|
||||||
|
if a=0 then
|
||||||
|
op:=OP_MOVE
|
||||||
else if ispowerof2(int64(a), powerval) then
|
else if ispowerof2(int64(a), powerval) then
|
||||||
begin
|
begin
|
||||||
a := powerval;
|
a := powerval;
|
||||||
op:= OP_SHL;
|
op:= OP_SHL;
|
||||||
end;
|
end;
|
||||||
exit;
|
end;
|
||||||
|
OP_ADD,OP_SUB:
|
||||||
|
begin
|
||||||
|
if a = 0 then
|
||||||
|
op:=OP_NONE;
|
||||||
end;
|
end;
|
||||||
OP_SAR,OP_SHL,OP_SHR:
|
OP_SAR,OP_SHL,OP_SHR:
|
||||||
begin
|
begin
|
||||||
if a = 0 then
|
if a = 0 then
|
||||||
optimize_op_const_reg := true;
|
op:=OP_NONE;
|
||||||
exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -349,6 +349,8 @@ interface
|
|||||||
hl4 : tasmlabel;
|
hl4 : tasmlabel;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
pass_left_right;
|
||||||
|
|
||||||
{The location.register will be filled in later (JM)}
|
{The location.register will be filled in later (JM)}
|
||||||
location_reset(location,LOC_REGISTER,OS_INT);
|
location_reset(location,LOC_REGISTER,OS_INT);
|
||||||
{Get a temp register and load the left value into it
|
{Get a temp register and load the left value into it
|
||||||
|
@ -33,9 +33,8 @@ interface
|
|||||||
procedure pass_2;override;
|
procedure pass_2;override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ti386shlshrnode = class(tshlshrnode)
|
ti386shlshrnode = class(tcgshlshrnode)
|
||||||
procedure pass_2;override;
|
procedure second_64bit;override;
|
||||||
{ everything will be handled in pass_2 }
|
|
||||||
function first_shlshr64bitint: tnode; override;
|
function first_shlshr64bitint: tnode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -165,7 +164,7 @@ implementation
|
|||||||
m_high:=m_high shr 1;
|
m_high:=m_high shr 1;
|
||||||
dec(l);
|
dec(l);
|
||||||
end;
|
end;
|
||||||
m:=m_high;
|
m:=dword(m_high);
|
||||||
s:=l;
|
s:=l;
|
||||||
if (m_high shr 31)<>0 then
|
if (m_high shr 31)<>0 then
|
||||||
a:=1
|
a:=1
|
||||||
@ -223,7 +222,7 @@ implementation
|
|||||||
d:=tordconstnode(right).value;
|
d:=tordconstnode(right).value;
|
||||||
if d>=$80000000 then
|
if d>=$80000000 then
|
||||||
begin
|
begin
|
||||||
emit_const_reg(A_CMP,S_L,d,hreg1);
|
emit_const_reg(A_CMP,S_L,aint(d),hreg1);
|
||||||
location.register:=cg.getintregister(exprasmlist,OS_INT);
|
location.register:=cg.getintregister(exprasmlist,OS_INT);
|
||||||
emit_const_reg(A_MOV,S_L,0,location.register);
|
emit_const_reg(A_MOV,S_L,0,location.register);
|
||||||
emit_const_reg(A_SBB,S_L,-1,location.register);
|
emit_const_reg(A_SBB,S_L,-1,location.register);
|
||||||
@ -359,29 +358,15 @@ implementation
|
|||||||
|
|
||||||
|
|
||||||
function ti386shlshrnode.first_shlshr64bitint: tnode;
|
function ti386shlshrnode.first_shlshr64bitint: tnode;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
result := nil;
|
result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure ti386shlshrnode.pass_2;
|
procedure ti386shlshrnode.second_64bit;
|
||||||
|
var
|
||||||
var hreg64hi,hreg64lo:Tregister;
|
hreg64hi,hreg64lo:Tregister;
|
||||||
op:Tasmop;
|
|
||||||
v : TConstExprInt;
|
v : TConstExprInt;
|
||||||
l1,l2,l3:Tasmlabel;
|
l1,l2,l3:Tasmlabel;
|
||||||
|
|
||||||
begin
|
|
||||||
secondpass(left);
|
|
||||||
secondpass(right);
|
|
||||||
|
|
||||||
{ determine operator }
|
|
||||||
if nodetype=shln then
|
|
||||||
op:=A_SHL
|
|
||||||
else
|
|
||||||
op:=A_SHR;
|
|
||||||
|
|
||||||
if is_64bitint(left.resulttype.def) then
|
|
||||||
begin
|
begin
|
||||||
location_reset(location,LOC_REGISTER,OS_64);
|
location_reset(location,LOC_REGISTER,OS_64);
|
||||||
|
|
||||||
@ -477,28 +462,6 @@ implementation
|
|||||||
location.register64.reglo:=hreg64lo;
|
location.register64.reglo:=hreg64lo;
|
||||||
location.register64.reghi:=hreg64hi;
|
location.register64.reghi:=hreg64hi;
|
||||||
end;
|
end;
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ load left operators in a register }
|
|
||||||
location_copy(location,left.location);
|
|
||||||
location_force_reg(exprasmlist,location,OS_INT,false);
|
|
||||||
|
|
||||||
{ shifting by a constant directly coded: }
|
|
||||||
if (right.nodetype=ordconstn) then
|
|
||||||
{ l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
|
|
||||||
emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ load right operators in a ECX }
|
|
||||||
cg.getcpuregister(exprasmlist,NR_ECX);
|
|
||||||
cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
|
|
||||||
|
|
||||||
{ right operand is in ECX }
|
|
||||||
cg.ungetcpuregister(exprasmlist,NR_ECX);
|
|
||||||
emit_reg_reg(op,S_L,NR_CL,location.register);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -404,11 +404,13 @@ unit cgcpu;
|
|||||||
opcode : tasmop;
|
opcode : tasmop;
|
||||||
r,r2 : Tregister;
|
r,r2 : Tregister;
|
||||||
begin
|
begin
|
||||||
{ need to emit opcode? }
|
optimize_op_const_reg(list, op, a, reg);
|
||||||
if optimize_op_const_reg(list, op, a, reg) then
|
|
||||||
exit;
|
|
||||||
opcode := topcg2tasmop[op];
|
opcode := topcg2tasmop[op];
|
||||||
case op of
|
case op of
|
||||||
|
OP_NONE :
|
||||||
|
begin
|
||||||
|
{ Opcode is optimized away }
|
||||||
|
end;
|
||||||
OP_ADD :
|
OP_ADD :
|
||||||
begin
|
begin
|
||||||
if (a >= 1) and (a <= 8) then
|
if (a >= 1) and (a <= 8) then
|
||||||
|
@ -459,8 +459,7 @@ interface
|
|||||||
ovloc.loc:=LOC_VOID;
|
ovloc.loc:=LOC_VOID;
|
||||||
|
|
||||||
pass_left_right;
|
pass_left_right;
|
||||||
force_reg_left_right(false,(cs_check_overflow in aktlocalswitches) and
|
force_reg_left_right(false,true);
|
||||||
(nodetype in [addn,subn]));
|
|
||||||
set_result_location_reg;
|
set_result_location_reg;
|
||||||
|
|
||||||
{ assume no overflow checking is required }
|
{ assume no overflow checking is required }
|
||||||
@ -634,8 +633,7 @@ interface
|
|||||||
ovloc.loc:=LOC_VOID;
|
ovloc.loc:=LOC_VOID;
|
||||||
|
|
||||||
pass_left_right;
|
pass_left_right;
|
||||||
force_reg_left_right(false,(cs_check_overflow in aktlocalswitches) and
|
force_reg_left_right(false,true);
|
||||||
(nodetype in [addn,subn,muln]));
|
|
||||||
set_result_location_reg;
|
set_result_location_reg;
|
||||||
|
|
||||||
{ determine if the comparison will be unsigned }
|
{ determine if the comparison will be unsigned }
|
||||||
@ -680,7 +678,7 @@ interface
|
|||||||
|
|
||||||
if nodetype<>subn then
|
if nodetype<>subn then
|
||||||
begin
|
begin
|
||||||
if (right.location.loc >LOC_CONSTANT) then
|
if (right.location.loc<>LOC_CONSTANT) then
|
||||||
cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,cgop,location.size,
|
cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,cgop,location.size,
|
||||||
left.location.register,right.location.register,
|
left.location.register,right.location.register,
|
||||||
location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
|
location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc)
|
||||||
@ -708,7 +706,7 @@ interface
|
|||||||
begin
|
begin
|
||||||
tmpreg:=cg.getintregister(exprasmlist,location.size);
|
tmpreg:=cg.getintregister(exprasmlist,location.size);
|
||||||
cg.a_load_const_reg(exprasmlist,location.size,
|
cg.a_load_const_reg(exprasmlist,location.size,
|
||||||
aword(left.location.value),tmpreg);
|
left.location.value,tmpreg);
|
||||||
cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
|
cg.a_op_reg_reg_reg_checkoverflow(exprasmlist,OP_SUB,location.size,
|
||||||
right.location.register,tmpreg,location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
|
right.location.register,tmpreg,location.register,checkoverflow and (cs_check_overflow in aktlocalswitches),ovloc);
|
||||||
end;
|
end;
|
||||||
|
@ -63,11 +63,6 @@ unit cgx86;
|
|||||||
procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
|
procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
|
||||||
procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
|
procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
|
||||||
|
|
||||||
procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
|
|
||||||
size: tcgsize; a: aint; src, dst: tregister); override;
|
|
||||||
procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
|
|
||||||
size: tcgsize; src1, src2, dst: tregister); override;
|
|
||||||
|
|
||||||
{ move instructions }
|
{ move instructions }
|
||||||
procedure a_load_const_reg(list : taasmoutput; tosize: tcgsize; a : aint;reg : tregister);override;
|
procedure a_load_const_reg(list : taasmoutput; tosize: tcgsize; a : aint;reg : tregister);override;
|
||||||
procedure a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aint;const ref : treference);override;
|
procedure a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aint;const ref : treference);override;
|
||||||
@ -160,8 +155,8 @@ unit cgx86;
|
|||||||
fmodule;
|
fmodule;
|
||||||
|
|
||||||
const
|
const
|
||||||
TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
|
TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_MOV,A_ADD,A_AND,A_DIV,
|
||||||
A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
|
A_IDIV,A_IMUL,A_MUL,A_NEG,A_NOT,A_OR,
|
||||||
A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
|
A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
|
||||||
|
|
||||||
TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
|
TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
|
||||||
@ -984,10 +979,10 @@ unit cgx86;
|
|||||||
opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
|
opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
|
||||||
( { scalar }
|
( { scalar }
|
||||||
( { OS_F32 }
|
( { OS_F32 }
|
||||||
A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP
|
A_NOP,A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP
|
||||||
),
|
),
|
||||||
( { OS_F64 }
|
( { OS_F64 }
|
||||||
A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP
|
A_NOP,A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
( { vectorized/packed }
|
( { vectorized/packed }
|
||||||
@ -995,10 +990,10 @@ unit cgx86;
|
|||||||
these
|
these
|
||||||
}
|
}
|
||||||
( { OS_F32 }
|
( { OS_F32 }
|
||||||
A_NOP,A_ADDPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
|
A_NOP,A_NOP,A_ADDPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
|
||||||
),
|
),
|
||||||
( { OS_F64 }
|
( { OS_F64 }
|
||||||
A_NOP,A_ADDPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPD
|
A_NOP,A_NOP,A_ADDPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPD
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -1062,9 +1057,11 @@ unit cgx86;
|
|||||||
tmpreg : tregister;
|
tmpreg : tregister;
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
begin
|
begin
|
||||||
|
optimize_op_const(op, a);
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
{ x86_64 only supports signed 32 bits constants directly }
|
{ x86_64 only supports signed 32 bits constants directly }
|
||||||
if (size in [OS_S64,OS_64]) and
|
if not(op in [OP_NONE,OP_MOVE) and
|
||||||
|
(size in [OS_S64,OS_64]) and
|
||||||
((a<low(longint)) or (a>high(longint))) then
|
((a<low(longint)) or (a>high(longint))) then
|
||||||
begin
|
begin
|
||||||
tmpreg:=getintregister(list,size);
|
tmpreg:=getintregister(list,size);
|
||||||
@ -1075,6 +1072,15 @@ unit cgx86;
|
|||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
check_register_size(size,reg);
|
check_register_size(size,reg);
|
||||||
case op of
|
case op of
|
||||||
|
OP_NONE :
|
||||||
|
begin
|
||||||
|
{ Opcode is optimized away }
|
||||||
|
end;
|
||||||
|
OP_MOVE :
|
||||||
|
begin
|
||||||
|
{ Optimized, replaced with a simple load }
|
||||||
|
a_load_const_reg(list,size,a,reg);
|
||||||
|
end;
|
||||||
OP_DIV, OP_IDIV:
|
OP_DIV, OP_IDIV:
|
||||||
begin
|
begin
|
||||||
if ispowerof2(int64(a),power) then
|
if ispowerof2(int64(a),power) then
|
||||||
@ -1155,11 +1161,13 @@ unit cgx86;
|
|||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
tmpref : treference;
|
tmpref : treference;
|
||||||
begin
|
begin
|
||||||
|
optimize_op_const(op, a);
|
||||||
tmpref:=ref;
|
tmpref:=ref;
|
||||||
make_simple_ref(list,tmpref);
|
make_simple_ref(list,tmpref);
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
{ x86_64 only supports signed 32 bits constants directly }
|
{ x86_64 only supports signed 32 bits constants directly }
|
||||||
if (size in [OS_S64,OS_64]) and
|
if not(op in [OP_NONE,OP_MOVE) and
|
||||||
|
(size in [OS_S64,OS_64]) and
|
||||||
((a<low(longint)) or (a>high(longint))) then
|
((a<low(longint)) or (a>high(longint))) then
|
||||||
begin
|
begin
|
||||||
tmpreg:=getintregister(list,size);
|
tmpreg:=getintregister(list,size);
|
||||||
@ -1169,6 +1177,15 @@ unit cgx86;
|
|||||||
end;
|
end;
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
Case Op of
|
Case Op of
|
||||||
|
OP_NONE :
|
||||||
|
begin
|
||||||
|
{ Opcode is optimized away }
|
||||||
|
end;
|
||||||
|
OP_MOVE :
|
||||||
|
begin
|
||||||
|
{ Optimized, replaced with a simple load }
|
||||||
|
a_load_const_ref(list,size,a,ref);
|
||||||
|
end;
|
||||||
OP_DIV, OP_IDIV:
|
OP_DIV, OP_IDIV:
|
||||||
Begin
|
Begin
|
||||||
if ispowerof2(int64(a),power) then
|
if ispowerof2(int64(a),power) then
|
||||||
@ -1266,10 +1283,11 @@ unit cgx86;
|
|||||||
internalerror(200109233);
|
internalerror(200109233);
|
||||||
OP_SHR,OP_SHL,OP_SAR:
|
OP_SHR,OP_SHL,OP_SAR:
|
||||||
begin
|
begin
|
||||||
getcpuregister(list,NR_CL);
|
{ Use ecx to load the value, that allows beter coalescing }
|
||||||
a_load_reg_reg(list,OS_8,OS_8,makeregsize(list,src,OS_8),NR_CL);
|
getcpuregister(list,NR_ECX);
|
||||||
list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,src));
|
a_load_reg_reg(list,size,OS_32,src,NR_ECX);
|
||||||
ungetcpuregister(list,NR_CL);
|
list.concat(taicpu.op_reg_reg(Topcg2asmop[op],tcgsize2opsize[size],NR_CL,dst));
|
||||||
|
ungetcpuregister(list,NR_ECX);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -1338,98 +1356,6 @@ unit cgx86;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tcgx86.a_op_const_reg_reg(list: taasmoutput; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister);
|
|
||||||
var
|
|
||||||
tmpref: treference;
|
|
||||||
power: longint;
|
|
||||||
{$ifdef x86_64}
|
|
||||||
tmpreg : tregister;
|
|
||||||
{$endif x86_64}
|
|
||||||
begin
|
|
||||||
{$ifdef x86_64}
|
|
||||||
{ x86_64 only supports signed 32 bits constants directly }
|
|
||||||
if (size in [OS_S64,OS_64]) and
|
|
||||||
((a<low(longint)) or (a>high(longint))) then
|
|
||||||
begin
|
|
||||||
tmpreg:=getintregister(list,size);
|
|
||||||
a_load_const_reg(list,size,a,tmpreg);
|
|
||||||
a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
{$endif x86_64}
|
|
||||||
check_register_size(size,src);
|
|
||||||
check_register_size(size,dst);
|
|
||||||
if tcgsize2size[size]<>tcgsize2size[OS_INT] then
|
|
||||||
begin
|
|
||||||
inherited a_op_const_reg_reg(list,op,size,a,src,dst);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
{ if we get here, we have to do a 32 bit calculation, guaranteed }
|
|
||||||
case op of
|
|
||||||
OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
|
|
||||||
OP_SAR:
|
|
||||||
{ can't do anything special for these }
|
|
||||||
inherited a_op_const_reg_reg(list,op,size,a,src,dst);
|
|
||||||
OP_IMUL:
|
|
||||||
begin
|
|
||||||
if not(cs_check_overflow in aktlocalswitches) and
|
|
||||||
ispowerof2(int64(a),power) then
|
|
||||||
{ can be done with a shift }
|
|
||||||
begin
|
|
||||||
inherited a_op_const_reg_reg(list,op,size,a,src,dst);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
list.concat(taicpu.op_const_reg_reg(A_IMUL,tcgsize2opsize[size],a,src,dst));
|
|
||||||
end;
|
|
||||||
OP_ADD, OP_SUB:
|
|
||||||
if (a = 0) then
|
|
||||||
a_load_reg_reg(list,size,size,src,dst)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
reference_reset(tmpref);
|
|
||||||
tmpref.base := src;
|
|
||||||
tmpref.offset := longint(a);
|
|
||||||
if op = OP_SUB then
|
|
||||||
tmpref.offset := -tmpref.offset;
|
|
||||||
list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[size],tmpref,dst));
|
|
||||||
end
|
|
||||||
else internalerror(200112302);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure tcgx86.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;size: tcgsize; src1, src2, dst: tregister);
|
|
||||||
var
|
|
||||||
tmpref: treference;
|
|
||||||
begin
|
|
||||||
check_register_size(size,src1);
|
|
||||||
check_register_size(size,src2);
|
|
||||||
check_register_size(size,dst);
|
|
||||||
if tcgsize2size[size]<>tcgsize2size[OS_INT] then
|
|
||||||
begin
|
|
||||||
inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
{ if we get here, we have to do a 32 bit calculation, guaranteed }
|
|
||||||
Case Op of
|
|
||||||
OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
|
|
||||||
OP_SAR,OP_SUB,OP_NOT,OP_NEG:
|
|
||||||
{ can't do anything special for these }
|
|
||||||
inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
|
|
||||||
OP_IMUL:
|
|
||||||
list.concat(taicpu.op_reg_reg_reg(A_IMUL,tcgsize2opsize[size],src1,src2,dst));
|
|
||||||
OP_ADD:
|
|
||||||
begin
|
|
||||||
reference_reset(tmpref);
|
|
||||||
tmpref.base := src1;
|
|
||||||
tmpref.index := src2;
|
|
||||||
tmpref.scalefactor := 1;
|
|
||||||
list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[size],tmpref,dst));
|
|
||||||
end
|
|
||||||
else internalerror(200112303);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{*************** compare instructructions ****************}
|
{*************** compare instructructions ****************}
|
||||||
|
|
||||||
procedure tcgx86.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
|
procedure tcgx86.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
|
||||||
|
@ -978,65 +978,17 @@ unit nx86add;
|
|||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
procedure tx86addnode.second_addordinal;
|
procedure tx86addnode.second_addordinal;
|
||||||
var
|
|
||||||
mboverflow : boolean;
|
|
||||||
op : tasmop;
|
|
||||||
opsize : tcgsize;
|
|
||||||
{ true, if unsigned types are compared }
|
|
||||||
unsigned : boolean;
|
|
||||||
{ true, if for sets subtractions the extra not should generated }
|
|
||||||
extra_not : boolean;
|
|
||||||
begin
|
begin
|
||||||
{ defaults }
|
{ filter unsigned MUL opcode, which requires special handling }
|
||||||
extra_not:=false;
|
if (nodetype=muln) and
|
||||||
mboverflow:=false;
|
(not(is_signed(left.resulttype.def)) or
|
||||||
unsigned:=not(is_signed(left.resulttype.def)) or
|
not(is_signed(right.resulttype.def))) then
|
||||||
not(is_signed(right.resulttype.def));
|
|
||||||
opsize:=def_cgsize(left.resulttype.def);
|
|
||||||
|
|
||||||
pass_left_right;
|
|
||||||
|
|
||||||
case nodetype of
|
|
||||||
addn :
|
|
||||||
begin
|
|
||||||
op:=A_ADD;
|
|
||||||
mboverflow:=true;
|
|
||||||
end;
|
|
||||||
muln :
|
|
||||||
begin
|
|
||||||
if unsigned then
|
|
||||||
op:=A_MUL
|
|
||||||
else
|
|
||||||
op:=A_IMUL;
|
|
||||||
mboverflow:=true;
|
|
||||||
end;
|
|
||||||
subn :
|
|
||||||
begin
|
|
||||||
op:=A_SUB;
|
|
||||||
mboverflow:=true;
|
|
||||||
end;
|
|
||||||
xorn :
|
|
||||||
op:=A_XOR;
|
|
||||||
orn :
|
|
||||||
op:=A_OR;
|
|
||||||
andn :
|
|
||||||
op:=A_AND;
|
|
||||||
else
|
|
||||||
internalerror(200304229);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ filter MUL, which requires special handling }
|
|
||||||
if op=A_MUL then
|
|
||||||
begin
|
begin
|
||||||
second_mul;
|
second_mul;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
left_must_be_reg(opsize,false);
|
inherited second_addordinal;
|
||||||
emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
|
|
||||||
location_freetemp(exprasmlist,right.location);
|
|
||||||
|
|
||||||
set_result_location_reg;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user