Skip to content

Commit

Permalink
i#5475 Add feature checks to AArch64 encoder (#5557)
Browse files Browse the repository at this point in the history
This patch implements the codec side of the AArch64 FEATURE_ support
patch, PR #5491. A feature name field is added to each opcode in
codec_*.txt files which is used to generate feature checks in the
encoder, e.g.

    switch (instr->opcode) {
    case OP_cas:
 #     if !defined(DR_HOST_NOT_TARGET) && !defined(STANDALONE_DECODER)
       if (!proc_has_feature(FEATURE_LSE))
           return ENCFAIL;
 #     endif
       enc = encode_opndsgen_08a07c00_001f03ff(pc, instr,..., di);
       if (enc != ENCFAIL)
           return enc;

Issues: #5475, #1569, #2626
  • Loading branch information
AssadHashmi authored Jul 11, 2022
1 parent ad6a637 commit 1ec09c3
Show file tree
Hide file tree
Showing 8 changed files with 1,422 additions and 1,389 deletions.
9 changes: 9 additions & 0 deletions core/arch/aarch64/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ proc_init_arch(void)
cpu_info.features.flags_aa64pfr0);
/* FIXME i#5474: Log all FEATURE_s for ID_AA64PFR0_EL1. */
LOG_FEATURE(FEATURE_FP16);
LOG_FEATURE(FEATURE_SVE);
});
#endif
}
Expand All @@ -147,6 +148,14 @@ bool
proc_has_feature(feature_bit_t f)
{
#ifndef DR_HOST_NOT_TARGET
/* Pretend features are supported for codec tests run on h/w which does not
* support all features.
*/
# if defined(BUILD_TESTS)
if (f == FEATURE_LSE || f == FEATURE_RDM || f == FEATURE_FP16 ||
f == FEATURE_DotProd || f == FEATURE_SVE)
return true;
# endif
ushort feat_nibble, feat_val, freg_nibble, feat_nsflag;
uint64 freg_val = 0;

Expand Down
3 changes: 2 additions & 1 deletion core/arch/proc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ typedef enum {
/* FIXME i#5474: Define all FEATURE_s for ID_AA64ISAR1_EL1 and ID_AA64PFR0_EL1. */
FEATURE_DPB = DEF_FEAT(AA64ISAR1, 0, 1, 0), /**< DC CVAP (AArch64) */
FEATURE_DPB2 = DEF_FEAT(AA64ISAR1, 0, 2, 0), /**< DC CVAP, DC CVADP (AArch64) */
FEATURE_FP16 = DEF_FEAT(AA64PFR0, 3, 1, 1), /**< Half-precision FP (AArch64) */
FEATURE_FP16 = DEF_FEAT(AA64PFR0, 4, 1, 1), /**< Half-precision FP (AArch64) */
FEATURE_SVE = DEF_FEAT(AA64PFR0, 8, 1, 1), /**< Scalable Vectors (AArch64) */
} feature_bit_t;
#endif

Expand Down
70 changes: 41 additions & 29 deletions core/ir/aarch64/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
opnd_header = '/* This file was generated by codec.py from opnd_defs.txt and the codec_<version>.txt files. */\n\n'
opcode_header = '/* This file was generated by codec.py from codec_<version>.txt files. */\n\n'

class Opcode:
def __init__(self, name, nzcv_rw, feat):
self.name = name
self.nzcv_rw = nzcv_rw
self.feat = feat

class Opnd:
def __init__(self, gen, used, must_be_set):
self.gen = gen
Expand All @@ -81,7 +87,7 @@ def __init__(self, opcode, opndset='', decode_clause='', decode_function=''):
self.decode_function = decode_function

class Pattern:
def __init__(self, pattern, opcode_bits, opnd_bits, high_soft_bits, opcode, opndset, enum):
def __init__(self, pattern, opcode_bits, opnd_bits, high_soft_bits, opcode, opndset, enum, feat):
self.pattern = pattern
self.opcode_bits = opcode_bits
self.opnd_bits = opnd_bits
Expand All @@ -91,6 +97,7 @@ def __init__(self, pattern, opcode_bits, opnd_bits, high_soft_bits, opcode, opnd
self.opcode = opcode
self.opndset = opndset
self.enum = enum
self.feat = feat

def __iter__(self):
for field in (self.opcode_bits, self.opnd_bits, self.opcode, self.opndset):
Expand Down Expand Up @@ -183,18 +190,18 @@ def indent_append(text):

if not else_str:
else_str = 'else '
if opc_props[pattern.opcode] != 'n':
if opc_props[pattern.opcode].nzcv_rw != 'n':
c[-1] = c[-1] + ' {'
# Uncomment this for debug output in generated code:
# indent_append(' // %s->%s' % (m, opc_props[m]))
if opc_props[pattern.opcode] == 'r':
# indent_append(' // %s->%s' % (m, opc_props[m].nzcv_rw))
if opc_props[pattern.opcode].nzcv_rw == 'r':
indent_append(' instr->eflags |= EFLAGS_READ_NZCV;')
elif opc_props[pattern.opcode] == 'w':
elif opc_props[pattern.opcode].nzcv_rw == 'w':
indent_append(' instr->eflags |= EFLAGS_WRITE_NZCV;')
elif opc_props[pattern.opcode] in ['rw', 'wr']:
elif opc_props[pattern.opcode].nzcv_rw in ['rw', 'wr']:
indent_append(' instr->eflags |= (EFLAGS_READ_NZCV | '
'EFLAGS_WRITE_NZCV);')
elif opc_props[pattern.opcode] in ['er', 'ew']:
elif opc_props[pattern.opcode].nzcv_rw in ['er', 'ew']:
indent_append(
' // instr->eflags handling for %s is '
'manually handled in codec.c\'s decode_common().' % pattern.opcode)
Expand All @@ -214,7 +221,7 @@ def indent_append(text):
else:
indent_append(' return decode_opnds%s(enc, dc, pc, '
'instr, OP_%s);' % (pattern.opndset, pattern.opcode))
if opc_props[pattern.opcode] != 'n':
if opc_props[pattern.opcode].nzcv_rw != 'n':
indent_append('}')
return
# Look for best bit to test. We aim to reduce the number of patterns
Expand Down Expand Up @@ -335,14 +342,15 @@ def generate_opndset_encoders(opndsettab, opndtab):
c.append('')
return '\n'.join(c) + '\n'

def generate_encoder(patterns, opndsettab, opndtab, curr_isa, next_isa):
def generate_encoder(patterns, opndsettab, opndtab, opc_props, curr_isa, next_isa):
c = []
case = dict()
for p in patterns:
(b, m, mn, f) = p
if not mn in case:
case[mn] = []
case[mn].append(p)
(opcode_bits, opnd_bits, opcode, opndset) = p
if not opcode in case:
case[opcode] = []
case[opcode].append(p)

c += ['static uint',
'encoder_' + curr_isa + '(byte *pc, instr_t *instr, decode_info_t *di)',
'{',
Expand All @@ -351,12 +359,17 @@ def generate_encoder(patterns, opndsettab, opndtab, curr_isa, next_isa):
' switch (instr->opcode) {']

def reorder_key(t):
b, m, mn, f = t
return (mn, f, b, m)

for mn in sorted(case):
c.append(' case OP_%s:' % mn)
patterns = sorted(case[mn], key=reorder_key)
opcode_bits, opnd_bits, opcode, opndset = t
return (opcode, opndset, opcode_bits, opnd_bits)

for opcode in sorted(case):
c.append(' case OP_%s:' % opcode)
if opc_props[opcode].feat != 'BASE':
c.append('# if !defined(DR_HOST_NOT_TARGET) && !defined(STANDALONE_DECODER)')
c.append(' if (!proc_has_feature(FEATURE_%s))' % opc_props[opcode].feat)
c.append(' return ENCFAIL;')
c.append('# endif')
patterns = sorted(case[opcode], key=reorder_key)
last_pattern = patterns.pop()
for pattern in patterns:
c.append(' enc = encode_opnds%s(pc, instr, 0x%08x, di);' % (
Expand Down Expand Up @@ -532,25 +545,24 @@ def read_codec_file(path):
for line in (l.split('#')[0].strip() for l in file):
if not line:
continue

if re.match('^[01x\^]{32} +[n|r|w|rw|wr|er|ew]+ +[0-9]+ +[a-zA-Z_0-9][a-zA-Z_0-9 ]*:[a-zA-Z_0-9 ]*$', line):
if re.match('^[01x\^]{32} +[n|r|w|rw|wr|er|ew]+ +[0-9]+ +[a-zA-Z0-9]* +[a-zA-Z_0-9][a-zA-Z_0-9 ]*:[a-zA-Z_0-9 ]*$', line):
# Syntax: pattern opcode opndtype* : opndtype*
pattern, nzcv_rw_flag, enum, opcode, args = line.split(None, 4)
pattern, nzcv_rw_flag, enum, feat, opcode, args = line.split(None, 5)
dsts, srcs = [a.split() for a in args.split(':')]
opcode_bits = int(re.sub('[\^x]', '0', pattern), 2)
opnd_bits = int(re.sub('x', '1', re.sub('[1\^]', '0', pattern)), 2)
high_soft_bits = int(re.sub('\^', '1', re.sub('[10x]', '0', pattern)), 2)
patterns.append(Pattern(pattern, opcode_bits, opnd_bits, high_soft_bits, opcode, (dsts, srcs), enum))
opc_props[opcode] = nzcv_rw_flag
patterns.append(Pattern(pattern, opcode_bits, opnd_bits, high_soft_bits, opcode, (dsts, srcs), enum, feat))
opc_props[opcode] = Opcode(opcode, nzcv_rw_flag, feat)
continue
if re.match('^[01x\^]{32} +[n|r|w|rw|wr|er|ew]+ +[0-9]+ +[a-zA-Z_0-9]+ +[a-zA-Z_0-9]+', line):
if re.match('^[01x\^]{32} +[n|r|w|rw|wr|er|ew]+ +[0-9]+ +[a-zA-Z0-9]* +[a-zA-Z_0-9]+ +[a-zA-Z_0-9]+', line):
# Syntax: pattern opcode opndset
pattern, nzcv_rw_flag, enum, opcode, opndset = line.split()
pattern, nzcv_rw_flag, enum, feat, opcode, opndset = line.split()
opcode_bits = int(re.sub('x', '0', pattern), 2)
opnd_bits = int(re.sub('x', '1', re.sub('1', '0', pattern)), 2)
high_soft_bits = int(re.sub('\^', '1', re.sub('[10x]', '0', pattern)), 2)
patterns.append(Pattern(pattern, opcode_bits, opnd_bits,high_soft_bits, opcode, opndset, enum))
opc_props[opcode] = nzcv_rw_flag
patterns.append(Pattern(pattern, opcode_bits, opnd_bits, high_soft_bits, opcode, opndset, enum, feat))
opc_props[opcode] = Opcode(opcode, nzcv_rw_flag, feat)
continue
raise Exception('Cannot parse line: %s in %s' % (line, path))
except IOError as e:
Expand Down Expand Up @@ -714,7 +726,7 @@ def main():
write_if_changed(os.path.join(output_dir, 'decode_gen_' + isa_version +'.h'),
codec_header(isa_version) + generate_decoder(patterns, opndsettab, opndtab, opc_props, isa_version, isa_versions[idx + 1]))
write_if_changed(os.path.join(output_dir, 'encode_gen_' + isa_version +'.h'),
codec_header(isa_version) + generate_encoder(patterns, opndsettab, opndtab, isa_version, isa_versions[idx + 1]))
codec_header(isa_version) + generate_encoder(patterns, opndsettab, opndtab, opc_props, isa_version, isa_versions[idx + 1]))
if isa_versions[idx + 1] == '':
break

Expand Down
20 changes: 10 additions & 10 deletions core/ir/aarch64/codec_sve.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@

# Instruction definitions:

00000100xx1xxxxx000000xxxxxxxxxx n 9 add z0 : z5 z16 bhsd_sz
00000100xx011010000xxxxxxxxxxxxx n 21 and z0 : p10_low z0 z5 bhsd_sz
00000100xx011011000xxxxxxxxxxxxx n 29 bic z0 : p10_low z0 z5 bhsd_sz
00000100xx011001000xxxxxxxxxxxxx n 90 eor z0 : p10_low z0 z5 bhsd_sz
00000100xx011000000xxxxxxxxxxxxx n 327 orr z0 : p10_low z0 z5 bhsd_sz
00000100xx1xxxxx000100xxxxxxxxxx n 403 sqadd z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000110xxxxxxxxxx n 425 sqsub z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000001xxxxxxxxxx n 470 sub z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000101xxxxxxxxxx n 531 uqadd z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000111xxxxxxxxxx n 538 uqsub z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000000xxxxxxxxxx n 9 SVE add z0 : z5 z16 bhsd_sz
00000100xx011010000xxxxxxxxxxxxx n 21 SVE and z0 : p10_low z0 z5 bhsd_sz
00000100xx011011000xxxxxxxxxxxxx n 29 SVE bic z0 : p10_low z0 z5 bhsd_sz
00000100xx011001000xxxxxxxxxxxxx n 90 SVE eor z0 : p10_low z0 z5 bhsd_sz
00000100xx011000000xxxxxxxxxxxxx n 327 SVE orr z0 : p10_low z0 z5 bhsd_sz
00000100xx1xxxxx000100xxxxxxxxxx n 403 SVE sqadd z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000110xxxxxxxxxx n 425 SVE sqsub z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000001xxxxxxxxxx n 470 SVE sub z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000101xxxxxxxxxx n 531 SVE uqadd z0 : z5 z16 bhsd_sz
00000100xx1xxxxx000111xxxxxxxxxx n 538 SVE uqsub z0 : z5 z16 bhsd_sz
Loading

0 comments on commit 1ec09c3

Please sign in to comment.