* remove some obsolete i386 specific code

* use a_optimize_const to remove useless opcodes

git-svn-id: trunk@2910 -
This commit is contained in:
peter 2006-03-13 16:37:08 +00:00
parent 2b9ccf6579
commit 588cccb3ca
8 changed files with 195 additions and 339 deletions

View File

@ -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];

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;