Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
0eff2df4
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0eff2df4
编写于
2月 23, 2019
作者:
R
Richard Henderson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
decodetree: Allow grouping of overlapping patterns
Signed-off-by:
N
Richard Henderson
<
richard.henderson@linaro.org
>
上级
eb6b87fa
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
207 addition
and
22 deletion
+207
-22
docs/devel/decodetree.rst
docs/devel/decodetree.rst
+58
-0
scripts/decodetree.py
scripts/decodetree.py
+143
-22
tests/decode/err_pattern_group_overlap1.decode
tests/decode/err_pattern_group_overlap1.decode
+6
-0
未找到文件。
docs/devel/decodetree.rst
浏览文件 @
0eff2df4
...
...
@@ -161,3 +161,61 @@ which will, in part, invoke::
and::
trans_addl_i(ctx, &arg_opi, insn)
Pattern Groups
==============
Syntax::
group := '{' ( pat_def | group )+ '}'
A *group* begins with a lone open-brace, with all subsequent lines
indented two spaces, and ending with a lone close-brace. Groups
may be nested, increasing the required indentation of the lines
within the nested group to two spaces per nesting level.
Unlike ungrouped patterns, grouped patterns are allowed to overlap.
Conflicts are resolved by selecting the patterns in order. If all
of the fixedbits for a pattern match, its translate function will
be called. If the translate function returns false, then subsequent
patterns within the group will be matched.
The following example from PA-RISC shows specialization of the *or*
instruction::
{
{
nop 000010 ----- ----- 0000 001001 0 00000
copy 000010 00000 r1:5 0000 001001 0 rt:5
}
or 000010 rt2:5 r1:5 cf:4 001001 0 rt:5
}
When the *cf* field is zero, the instruction has no side effects,
and may be specialized. When the *rt* field is zero, the output
is discarded and so the instruction has no effect. When the *rt2*
field is zero, the operation is ``reg[rt] | 0`` and so encodes
the canonical register copy operation.
The output from the generator might look like::
switch (insn & 0xfc000fe0) {
case 0x08000240:
/* 000010.. ........ ....0010 010..... */
if ((insn & 0x0000f000) == 0x00000000) {
/* 000010.. ........ 00000010 010..... */
if ((insn & 0x0000001f) == 0x00000000) {
/* 000010.. ........ 00000010 01000000 */
extract_decode_Fmt_0(&u.f_decode0, insn);
if (trans_nop(ctx, &u.f_decode0)) return true;
}
if ((insn & 0x03e00000) == 0x00000000) {
/* 00001000 000..... 00000010 010..... */
extract_decode_Fmt_1(&u.f_decode1, insn);
if (trans_copy(ctx, &u.f_decode1)) return true;
}
}
extract_decode_Fmt_2(&u.f_decode2, insn);
if (trans_or(ctx, &u.f_decode2)) return true;
return false;
}
scripts/decodetree.py
浏览文件 @
0eff2df4
...
...
@@ -31,6 +31,7 @@ fields = {}
arguments
=
{}
formats
=
{}
patterns
=
[]
allpatterns
=
[]
translate_prefix
=
'trans'
translate_scope
=
'static '
...
...
@@ -300,13 +301,7 @@ class General:
self
.
fields
=
flds
def
__str__
(
self
):
r
=
self
.
name
if
self
.
base
:
r
=
r
+
' '
+
self
.
base
.
name
else
:
r
=
r
+
' '
+
str
(
self
.
fields
)
r
=
r
+
' '
+
str_match_bits
(
self
.
fixedbits
,
self
.
fixedmask
)
return
r
return
self
.
name
+
' '
+
str_match_bits
(
self
.
fixedbits
,
self
.
fixedmask
)
def
str1
(
self
,
i
):
return
str_indent
(
i
)
+
self
.
__str__
()
...
...
@@ -353,6 +348,47 @@ class Pattern(General):
# end Pattern
class
MultiPattern
(
General
):
"""Class representing an overlapping set of instruction patterns"""
def
__init__
(
self
,
lineno
,
pats
,
fixb
,
fixm
,
udfm
):
self
.
file
=
input_file
self
.
lineno
=
lineno
self
.
pats
=
pats
self
.
base
=
None
self
.
fixedbits
=
fixb
self
.
fixedmask
=
fixm
self
.
undefmask
=
udfm
def
__str__
(
self
):
r
=
"{"
for
p
in
self
.
pats
:
r
=
r
+
' '
+
str
(
p
)
return
r
+
"}"
def
output_decl
(
self
):
for
p
in
self
.
pats
:
p
.
output_decl
()
def
output_code
(
self
,
i
,
extracted
,
outerbits
,
outermask
):
global
translate_prefix
ind
=
str_indent
(
i
)
for
p
in
self
.
pats
:
if
outermask
!=
p
.
fixedmask
:
innermask
=
p
.
fixedmask
&
~
outermask
innerbits
=
p
.
fixedbits
&
~
outermask
output
(
ind
,
'if ((insn & '
,
'0x{0:08x}) == 0x{1:08x}'
.
format
(
innermask
,
innerbits
),
') {
\n
'
)
output
(
ind
,
' /* '
,
str_match_bits
(
p
.
fixedbits
,
p
.
fixedmask
),
' */
\n
'
)
p
.
output_code
(
i
+
4
,
extracted
,
p
.
fixedbits
,
p
.
fixedmask
)
output
(
ind
,
'}
\n
'
)
else
:
p
.
output_code
(
i
,
extracted
,
p
.
fixedbits
,
p
.
fixedmask
)
#end MultiPattern
def
parse_field
(
lineno
,
name
,
toks
):
"""Parse one instruction field from TOKS at LINENO"""
global
fields
...
...
@@ -505,6 +541,7 @@ def parse_generic(lineno, is_format, name, toks):
global
arguments
global
formats
global
patterns
global
allpatterns
global
re_ident
global
insnwidth
global
insnmask
...
...
@@ -649,6 +686,7 @@ def parse_generic(lineno, is_format, name, toks):
pat
=
Pattern
(
name
,
lineno
,
fmt
,
fixedbits
,
fixedmask
,
undefmask
,
fieldmask
,
flds
)
patterns
.
append
(
pat
)
allpatterns
.
append
(
pat
)
# Validate the masks that we have assembled.
if
fieldmask
&
fixedmask
:
...
...
@@ -667,17 +705,66 @@ def parse_generic(lineno, is_format, name, toks):
.
format
(
allbits
^
insnmask
))
# end parse_general
def
build_multi_pattern
(
lineno
,
pats
):
"""Validate the Patterns going into a MultiPattern."""
global
patterns
global
insnmask
if
len
(
pats
)
<
2
:
error
(
lineno
,
'less than two patterns within braces'
)
fixedmask
=
insnmask
undefmask
=
insnmask
# Collect fixed/undefmask for all of the children.
# Move the defining lineno back to that of the first child.
for
p
in
pats
:
fixedmask
&=
p
.
fixedmask
undefmask
&=
p
.
undefmask
if
p
.
lineno
<
lineno
:
lineno
=
p
.
lineno
repeat
=
True
while
repeat
:
if
fixedmask
==
0
:
error
(
lineno
,
'no overlap in patterns within braces'
)
fixedbits
=
None
for
p
in
pats
:
thisbits
=
p
.
fixedbits
&
fixedmask
if
fixedbits
is
None
:
fixedbits
=
thisbits
elif
fixedbits
!=
thisbits
:
fixedmask
&=
~
(
fixedbits
^
thisbits
)
break
else
:
repeat
=
False
mp
=
MultiPattern
(
lineno
,
pats
,
fixedbits
,
fixedmask
,
undefmask
)
patterns
.
append
(
mp
)
# end build_multi_pattern
def
parse_file
(
f
):
"""Parse all of the patterns within a file"""
global
patterns
# Read all of the lines of the file. Concatenate lines
# ending in backslash; discard empty lines and comments.
toks
=
[]
lineno
=
0
nesting
=
0
saved_pats
=
[]
for
line
in
f
:
lineno
+=
1
# Expand and strip spaces, to find indent.
line
=
line
.
rstrip
()
line
=
line
.
expandtabs
()
len1
=
len
(
line
)
line
=
line
.
lstrip
()
len2
=
len
(
line
)
# Discard comments
end
=
line
.
find
(
'#'
)
if
end
>=
0
:
...
...
@@ -687,10 +774,18 @@ def parse_file(f):
if
len
(
toks
)
!=
0
:
# Next line after continuation
toks
.
extend
(
t
)
elif
len
(
t
)
==
0
:
# Empty line
continue
else
:
# Allow completely blank lines.
if
len1
==
0
:
continue
indent
=
len1
-
len2
# Empty line due to comment.
if
len
(
t
)
==
0
:
# Indentation must be correct, even for comment lines.
if
indent
!=
nesting
:
error
(
lineno
,
'indentation '
,
indent
,
' != '
,
nesting
)
continue
start_lineno
=
lineno
toks
=
t
# Continuation?
...
...
@@ -698,21 +793,47 @@ def parse_file(f):
toks
.
pop
()
continue
if
len
(
toks
)
<
2
:
error
(
lineno
,
'short line'
)
name
=
toks
[
0
]
del
toks
[
0
]
# End nesting?
if
name
==
'}'
:
if
nesting
==
0
:
error
(
start_lineno
,
'mismatched close brace'
)
if
len
(
toks
)
!=
0
:
error
(
start_lineno
,
'extra tokens after close brace'
)
nesting
-=
2
if
indent
!=
nesting
:
error
(
start_lineno
,
'indentation '
,
indent
,
' != '
,
nesting
)
pats
=
patterns
patterns
=
saved_pats
.
pop
()
build_multi_pattern
(
lineno
,
pats
)
toks
=
[]
continue
# Everything else should have current indentation.
if
indent
!=
nesting
:
error
(
start_lineno
,
'indentation '
,
indent
,
' != '
,
nesting
)
# Start nesting?
if
name
==
'{'
:
if
len
(
toks
)
!=
0
:
error
(
start_lineno
,
'extra tokens after open brace'
)
saved_pats
.
append
(
patterns
)
patterns
=
[]
nesting
+=
2
toks
=
[]
continue
# Determine the type of object needing to be parsed.
if
name
[
0
]
==
'%'
:
parse_field
(
lineno
,
name
[
1
:],
toks
)
parse_field
(
start_
lineno
,
name
[
1
:],
toks
)
elif
name
[
0
]
==
'&'
:
parse_arguments
(
lineno
,
name
[
1
:],
toks
)
parse_arguments
(
start_
lineno
,
name
[
1
:],
toks
)
elif
name
[
0
]
==
'@'
:
parse_generic
(
lineno
,
True
,
name
[
1
:],
toks
)
parse_generic
(
start_
lineno
,
True
,
name
[
1
:],
toks
)
else
:
parse_generic
(
lineno
,
False
,
name
,
toks
)
parse_generic
(
start_
lineno
,
False
,
name
,
toks
)
toks
=
[]
# end parse_file
...
...
@@ -789,11 +910,10 @@ def build_tree(pats, outerbits, outermask):
innermask
&=
i
.
fixedmask
if
innermask
==
0
:
pnames
=
[]
text
=
'overlapping patterns:'
for
p
in
pats
:
pnames
.
append
(
p
.
name
+
':'
+
p
.
file
+
':'
+
str
(
p
.
lineno
))
error_with_file
(
pats
[
0
].
file
,
pats
[
0
].
lineno
,
'overlapping patterns:'
,
pnames
)
text
+=
'
\n
'
+
p
.
file
+
':'
+
str
(
p
.
lineno
)
+
': '
+
str
(
p
)
error_with_file
(
pats
[
0
].
file
,
pats
[
0
].
lineno
,
text
)
fullmask
=
outermask
|
innermask
...
...
@@ -846,6 +966,7 @@ def main():
global
arguments
global
formats
global
patterns
global
allpatterns
global
translate_scope
global
translate_prefix
global
output_fd
...
...
@@ -907,7 +1028,7 @@ def main():
# Make sure that the argument sets are the same, and declare the
# function only once.
out_pats
=
{}
for
i
in
patterns
:
for
i
in
all
patterns
:
if
i
.
name
in
out_pats
:
p
=
out_pats
[
i
.
name
]
if
i
.
base
.
base
!=
p
.
base
.
base
:
...
...
tests/decode/err_pattern_group_overlap1.decode
0 → 100644
浏览文件 @
0eff2df4
one 00000000000000000000000000000000
{
two 0000000000000000000000000000000 s:1
three 000000000000000000000000000000 s:1 0
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录