mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-29 21:20:24 +02:00
+ positive number MOD power of 2 now done with AND instruction
* fix to division of positive numbers by power of 2 * the result of a MOD is left in EDX if possible
This commit is contained in:
parent
26fa893ed7
commit
89405ceeed
@ -53,11 +53,14 @@ implementation
|
||||
procedure secondmoddiv(var p : ptree);
|
||||
var
|
||||
hreg1 : tregister;
|
||||
pushed,popeax,popedx : boolean;
|
||||
shrdiv, andmod, pushed,popeax,popedx : boolean;
|
||||
|
||||
power : longint;
|
||||
hl : plabel;
|
||||
|
||||
begin
|
||||
shrdiv := false;
|
||||
andmod := false;
|
||||
secondpass(p^.left);
|
||||
set_location(p^.location,p^.left^.location);
|
||||
pushed:=maybe_push(p^.right^.registers32,p);
|
||||
@ -87,29 +90,46 @@ implementation
|
||||
|
||||
if (p^.treetype=divn) and (p^.right^.treetype=ordconstn) and
|
||||
ispowerof2(p^.right^.value,power) then
|
||||
begin
|
||||
exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hreg1,hreg1)));
|
||||
getlabel(hl);
|
||||
emitjmp(C_NS,hl);
|
||||
if power=1 then
|
||||
exprasmlist^.concat(new(pai386,op_reg(A_INC,S_L,hreg1)))
|
||||
else
|
||||
exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,p^.right^.value-1,hreg1)));
|
||||
emitlab(hl);
|
||||
exprasmlist^.concat(new(pai386,op_const_reg(A_SAR,S_L,power,hreg1)));
|
||||
end
|
||||
Begin
|
||||
shrdiv := true;
|
||||
{for signed numbers, the numerator must be adjusted before the
|
||||
shift instruction, but not wih unsigned numbers! Otherwise,
|
||||
"Cardinal($ffffffff) div 16" overflows! (JM)}
|
||||
If is_signed(p^.left^.resulttype) Then
|
||||
Begin
|
||||
exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hreg1,hreg1)));
|
||||
getlabel(hl);
|
||||
emitjmp(C_NS,hl);
|
||||
if power=1 then
|
||||
exprasmlist^.concat(new(pai386,op_reg(A_INC,S_L,hreg1)))
|
||||
else
|
||||
exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,p^.right^.value-1,hreg1)));
|
||||
emitlab(hl);
|
||||
exprasmlist^.concat(new(pai386,op_const_reg(A_SAR,S_L,power,hreg1)));
|
||||
End
|
||||
Else
|
||||
exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_L,power,hreg1)));
|
||||
End
|
||||
else
|
||||
if (p^.treetype=modn) and (p^.right^.treetype=ordconstn) and
|
||||
ispowerof2(p^.right^.value,power) and Not(is_signed(p^.left^.resulttype)) Then
|
||||
{is there a similar trick for MOD'ing signed numbers? (JM)}
|
||||
Begin
|
||||
exprasmlist^.concat(new(pai386,op_const_reg(A_AND,S_L,p^.right^.value-1,hreg1)));
|
||||
andmod := true;
|
||||
End
|
||||
else
|
||||
begin
|
||||
{ bring denominator to EDI }
|
||||
{ EDI is always free, it's }
|
||||
{ only used for temporary }
|
||||
{ purposes }
|
||||
if (p^.right^.location.loc<>LOC_REGISTER) and
|
||||
(p^.right^.location.loc<>LOC_CREGISTER) then
|
||||
begin
|
||||
del_reference(p^.right^.location.reference);
|
||||
p^.left^.location.loc:=LOC_REGISTER;
|
||||
exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI)));
|
||||
if (p^.right^.location.loc<>LOC_REGISTER) and
|
||||
(p^.right^.location.loc<>LOC_CREGISTER) then
|
||||
begin
|
||||
del_reference(p^.right^.location.reference);
|
||||
p^.left^.location.loc:=LOC_REGISTER;
|
||||
exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI)));
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -120,14 +140,14 @@ implementation
|
||||
popeax:=false;
|
||||
if hreg1=R_EDX then
|
||||
begin
|
||||
if not(R_EAX in unused) then
|
||||
if not(R_EAX in unused) then
|
||||
begin
|
||||
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
|
||||
popeax:=true;
|
||||
end;
|
||||
emit_reg_reg(A_MOV,S_L,R_EDX,R_EAX);
|
||||
emit_reg_reg(A_MOV,S_L,R_EDX,R_EAX);
|
||||
end
|
||||
else
|
||||
else
|
||||
begin
|
||||
if not(R_EDX in unused) then
|
||||
begin
|
||||
@ -166,18 +186,47 @@ implementation
|
||||
end
|
||||
else
|
||||
if hreg1<>R_EAX then
|
||||
emit_reg_reg(A_MOV,S_L,R_EAX,hreg1);
|
||||
Begin
|
||||
ungetregister32(hreg1);
|
||||
hreg1 := getexplicitregister32(R_EAX);
|
||||
{ I don't think it's possible that now hreg1 <> R_EAX
|
||||
since popeax is false, but for all certainty I do
|
||||
support that situation (JM)}
|
||||
if hreg1 <> R_EAX then
|
||||
emit_reg_reg(A_MOV,S_L,R_EAX,hreg1);
|
||||
end;
|
||||
end
|
||||
else
|
||||
emit_reg_reg(A_MOV,S_L,R_EDX,hreg1);
|
||||
{if we did the mod by an "and", the result is in hreg1 and
|
||||
EDX certainly hasn't been pushed (JM)}
|
||||
if not(andmod) Then
|
||||
if popedx then
|
||||
{the mod was done by an (i)div (so the result is now in
|
||||
edx), but edx was occupied prior to the division, so
|
||||
move the result into a safe place (JM)}
|
||||
emit_reg_reg(A_MOV,S_L,R_EDX,hreg1)
|
||||
else
|
||||
Begin
|
||||
{Get rid of the unnecessary hreg1 if possible (same as with
|
||||
EAX in divn) (JM)}
|
||||
ungetregister32(hreg1);
|
||||
hreg1 := getexplicitregister32(R_EDX);
|
||||
if hreg1 <> R_EDX then
|
||||
emit_reg_reg(A_MOV,S_L,R_EDX,hreg1);;
|
||||
End;
|
||||
if popeax then
|
||||
exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
|
||||
if popedx then
|
||||
exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDX)));
|
||||
end;
|
||||
{ this registers are always used when div/mod are present }
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EAX));
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EDX));
|
||||
If not(andmod or shrdiv) then
|
||||
{andmod and shrdiv only use hreg1 (which is already in usedinproc,
|
||||
since it was acquired with getregister), the others also use both
|
||||
EAX and EDX (JM)}
|
||||
Begin
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EAX));
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EDX));
|
||||
End;
|
||||
clear_location(p^.location);
|
||||
p^.location.loc:=LOC_REGISTER;
|
||||
p^.location.register:=hreg1;
|
||||
@ -768,7 +817,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.22 1999-05-01 13:24:11 peter
|
||||
Revision 1.23 1999-05-08 20:41:08 jonas
|
||||
+ positive number MOD power of 2 now done with AND instruction
|
||||
* fix to division of positive numbers by power of 2
|
||||
* the result of a MOD is left in EDX if possible
|
||||
|
||||
Revision 1.22 1999/05/01 13:24:11 peter
|
||||
* merged nasm compiler
|
||||
* old asm moved to oldasm/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user