summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2006-03-08 10:26:38 +0000
committerpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2006-03-08 10:26:38 +0000
commit84de4a3353ee828dc9a302cc4d061aa002ea1913 (patch)
tree753005c6dfb9139c76838300997ae77a264f1dd7
parent5ebe36448d7470c6dfdc9fd234839594c1d8acc1 (diff)
downloadfpc-84de4a3353ee828dc9a302cc4d061aa002ea1913.tar.gz
* optimize and cleanup matches()
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/linker@2809 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/x86/aasmcpu.pas170
1 files changed, 81 insertions, 89 deletions
diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas
index f4753d1a4f..8263f045a2 100644
--- a/compiler/x86/aasmcpu.pas
+++ b/compiler/x86/aasmcpu.pas
@@ -258,7 +258,7 @@ interface
insentry : PInsEntry;
function InsEnd:longint;
procedure create_ot(objdata:TObjData);
- function Matches(p:PInsEntry):longint;
+ function Matches(p:PInsEntry):boolean;
function calcsize(p:PInsEntry):shortint;
procedure gencode(objdata:TObjData);
function NeedAddrPrefix(opidx:byte):boolean;
@@ -288,11 +288,12 @@ implementation
const
{Instruction flags }
IF_NONE = $00000000;
- IF_SM = $00000001; { size match first two operands }
+ IF_SM = $00000001; { size match first two operands }
IF_SM2 = $00000002;
IF_SB = $00000004; { unsized operands can't be non-byte }
IF_SW = $00000008; { unsized operands can't be non-word }
IF_SD = $00000010; { unsized operands can't be nondword }
+ IF_SMASK = $0000001f;
IF_AR0 = $00000020; { SB, SW, SD applies to argument 0 }
IF_AR1 = $00000040; { SB, SW, SD applies to argument 1 }
IF_AR2 = $00000060; { SB, SW, SD applies to argument 2 }
@@ -1082,7 +1083,7 @@ implementation
end;
- function taicpu.Matches(p:PInsEntry):longint;
+ function taicpu.Matches(p:PInsEntry):boolean;
{ * IF_SM stands for Size Match: any operand whose size is not
* explicitly specified by the template is `really' intended to be
* the same size as the first size-specified operand.
@@ -1104,106 +1105,97 @@ implementation
* required to have unspecified size in the instruction too...)
}
var
+ insot,
+ insflags,
+ currot,
i,j,asize,oprs : longint;
siz : array[0..2] of longint;
begin
- Matches:=100;
+ result:=false;
{ Check the opcode and operands }
if (p^.opcode<>opcode) or (p^.ops<>ops) then
- begin
- Matches:=0;
- exit;
- end;
-
- { Check that no spurious colons or TOs are present }
- for i:=0 to p^.ops-1 do
- if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
- begin
- Matches:=0;
- exit;
- end;
+ exit;
- { Check that the operand flags all match up }
for i:=0 to p^.ops-1 do
begin
- if ((p^.optypes[i] and (not oper[i]^.ot)) or
- ((p^.optypes[i] and OT_SIZE_MASK) and
- ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
- begin
- if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
- (oper[i]^.ot and OT_SIZE_MASK))<>0 then
- begin
- Matches:=0;
- exit;
- end
- else
- Matches:=1;
- end;
- end;
-
- { Check operand sizes }
- { as default an untyped size can get all the sizes, this is different
- from nasm, but else we need to do a lot checking which opcodes want
- size or not with the automatic size generation }
- asize:=longint($ffffffff);
- if (p^.flags and IF_SB)<>0 then
- asize:=OT_BITS8
- else if (p^.flags and IF_SW)<>0 then
- asize:=OT_BITS16
- else if (p^.flags and IF_SD)<>0 then
- asize:=OT_BITS32;
- if (p^.flags and IF_ARMASK)<>0 then
- begin
- siz[0]:=0;
- siz[1]:=0;
- siz[2]:=0;
- if (p^.flags and IF_AR0)<>0 then
- siz[0]:=asize
- else if (p^.flags and IF_AR1)<>0 then
- siz[1]:=asize
- else if (p^.flags and IF_AR2)<>0 then
- siz[2]:=asize;
- end
- else
- begin
- { we can leave because the size for all operands is forced to be
- the same
- but not if IF_SB IF_SW or IF_SD is set PM }
- if asize=-1 then
+ insot:=p^.optypes[i];
+ currot:=oper[i]^.ot;
+ { Check that the operand flags }
+ if (insot and (not currot))<>0 then
+ exit;
+ { Check if the passed operand size matches with the required
+ instruction operand size. The second 'and' with insot is used
+ to allow matching with undefined size }
+ if ((currot xor insot) and insot and OT_SIZE_MASK)<>0 then
exit;
- siz[0]:=asize;
- siz[1]:=asize;
- siz[2]:=asize;
end;
- if (p^.flags and (IF_SM or IF_SM2))<>0 then
- begin
- if (p^.flags and IF_SM2)<>0 then
- oprs:=2
- else
- oprs:=p^.ops;
- for i:=0 to oprs-1 do
- if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
+ { Check operand sizes }
+ insflags:=p^.flags;
+ if insflags and IF_SMASK<>0 then
+ begin
+ { as default an untyped size can get all the sizes, this is different
+ from nasm, but else we need to do a lot checking which opcodes want
+ size or not with the automatic size generation }
+ asize:=-1;
+ if (insflags and IF_SB)<>0 then
+ asize:=OT_BITS8
+ else if (insflags and IF_SW)<>0 then
+ asize:=OT_BITS16
+ else if (insflags and IF_SD)<>0 then
+ asize:=OT_BITS32;
+ if (insflags and IF_ARMASK)<>0 then
+ begin
+ siz[0]:=0;
+ siz[1]:=0;
+ siz[2]:=0;
+ if (insflags and IF_AR0)<>0 then
+ siz[0]:=asize
+ else if (insflags and IF_AR1)<>0 then
+ siz[1]:=asize
+ else if (insflags and IF_AR2)<>0 then
+ siz[2]:=asize;
+ end
+ else
begin
- for j:=0 to oprs-1 do
- siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
- break;
+ siz[0]:=asize;
+ siz[1]:=asize;
+ siz[2]:=asize;
end;
- end
- else
- oprs:=2;
- { Check operand sizes }
- for i:=0 to p^.ops-1 do
- begin
- if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
- ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
- { Immediates can always include smaller size }
- ((oper[i]^.ot and OT_IMMEDIATE)=0) and
- (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
- Matches:=2;
- end;
+ if (insflags and (IF_SM or IF_SM2))<>0 then
+ begin
+ if (insflags and IF_SM2)<>0 then
+ oprs:=2
+ else
+ oprs:=p^.ops;
+ for i:=0 to oprs-1 do
+ if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
+ begin
+ for j:=0 to oprs-1 do
+ siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
+ break;
+ end;
+ end
+ else
+ oprs:=2;
+
+ { Check operand sizes }
+ for i:=0 to p^.ops-1 do
+ begin
+ insot:=p^.optypes[i];
+ currot:=oper[i]^.ot;
+ if ((insot and OT_SIZE_MASK)=0) and
+ ((currot and OT_SIZE_MASK and (not siz[i]))<>0) and
+ { Immediates can always include smaller size }
+ ((currot and OT_IMMEDIATE)=0) and
+ (((insot and OT_SIZE_MASK) or siz[i])<(currot and OT_SIZE_MASK)) then
+ exit;
+ end;
+ end;
+
+ result:=true;
end;
@@ -1270,7 +1262,7 @@ implementation
insentry:=@instab[i];
while (insentry^.opcode=opcode) do
begin
- if matches(insentry)=100 then
+ if matches(insentry) then
begin
result:=true;
exit;