Skip to content

Commit

Permalink
i#4393 New AArch64 codec implementation
Browse files Browse the repository at this point in the history
This patch is an example of the code which will be generated from a
machine readable specification (MRS) to decode and encode AArch64
instructions from v8.1 onwards.

It is provided for review and discussion purposes, in order to resolve
any issues which may arise and to make visible what changes to expect.

This patch does not include the MRS, the parser or generator, just an
example of the target code which we intend to generate, based on the
v8.1 SQRDMLAH instruction.

Issue: #4393, #3044, #2626
  • Loading branch information
AssadHashmi committed Apr 8, 2022
1 parent eae2f4e commit 4146c21
Show file tree
Hide file tree
Showing 7 changed files with 930 additions and 20 deletions.
25 changes: 23 additions & 2 deletions core/ir/aarch64/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -5055,6 +5055,25 @@ encode_opnds_tbz(byte *pc, instr_t *instr, uint enc, decode_info_t *di)
return ENCFAIL;
}

/* Function(s) used by new codec. */

/* Halfword and short element size. This is the same as encode_opnd_hs_sz()
* except that the shift of the size value to place it in the correct part of
* the encoding is not done here. That placement is instruction specific and so
* is done by each instruction's enc_*() function. In general the positioning
* of operand encodings in instruction encodings should be done by each
* instruction's encoding function, rather than an operand's encoding function.
*/
static inline bool
get_el_hs_sz(OUT uint *elsz_out, opnd_t opnd)
{
ptr_int_t val = opnd_get_immed_int(opnd);
if (val < 1 || val > 2)
return false;
*elsz_out = val;
return true;
}

/******************************************************************************/

/* Include automatically generated decoder and encoder files. Decode and encode
Expand All @@ -5067,11 +5086,13 @@ encode_opnds_tbz(byte *pc, instr_t *instr, uint enc, decode_info_t *di)
#include "opnd_encode_funcs.h"
#include "decode_gen_sve.h"
#include "decode_gen_v82.h"
#include "decode_gen_v81.h"
#include "decode_v81.h"
#include "decode_gen_v81.h" /* Redirects decoding to decode_v81.h */
#include "decode_gen_v80.h"
#include "encode_gen_sve.h"
#include "encode_gen_v82.h"
#include "encode_gen_v81.h"
#include "encode_v81.h"
#include "encode_gen_v81.h" /* Redirects encoding to encode_v81.h */
#include "encode_gen_v80.h"

/******************************************************************************/
Expand Down
28 changes: 28 additions & 0 deletions core/ir/aarch64/codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,32 @@ decode_common(dcontext_t *dcontext, byte *pc, byte *orig_pc, instr_t *instr);
uint
encode_common(byte *pc, instr_t *i, decode_info_t *di);

/* Types and macros used by new codec. */

/* Bit extraction macro used extensively by automatically generated decoder and
* encoder functions.
*/
#define BITS(_enc, bitmax, bitmin) \
(( ((uint32)(_enc)) >> (bitmin)) \
& (uint32)((1ULL << ((bitmax) - (bitmin) + 1)) - 1ULL))

/* Decoding is based on a key/value mapping (decode_map) where the key
* (enc_bits) is a unique set of up to 32 bits representing an instruction
* which is decoded by a function (decode_fn).
*/
typedef bool (decode_func_ptr)(dcontext_t *dcontext, uint enc, instr_t *instr);

typedef struct dmap {
uint32 enc_bits;
decode_func_ptr *decode_fn;
} decode_map;

/* Encoding function call-and-check macro used extensively by automatically
* generated encoder switch/case clauses.
*/
#define ENCODE_IF_MATCH(ENCODE_FUNCTION) \
enc = ENCODE_FUNCTION(instr); \
if (enc != ENCFAIL) \
return enc;

#endif /* CODEC_H */
38 changes: 30 additions & 8 deletions core/ir/aarch64/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ def generate_opndset_decoders(opndsettab, opndtab):
FALLTHROUGH.values()]
c += ['\n']
for name in sorted(opndsettab):
# Ignore dummy codec_*.txt entries. This suppresses generation of this
# decoder function for instructions handled by the new decoder.
if name == 'gen_00000000_00000000':
return '\n'
opnd_set = opndsettab[name]
(dsts, srcs) = (opnd_set.dsts, opnd_set.srcs)
c += ['/* %s <- %s */' % (opnd_set.dsts, opnd_set.srcs)]
Expand Down Expand Up @@ -255,10 +259,17 @@ def indent_append(text):
c = ['static bool',
'decoder_' + curr_isa + '(uint enc, dcontext_t *dc, byte *pc, instr_t *instr)',
'{']
gen(c, patterns, 1)
for opcode in FALLTHROUGH.values():
c += [' %s' % opcode.decode_clause]
c += [' %s' % opcode.decode_function]
if curr_isa != 'v81':
gen(c, patterns, 1)
for opcode in FALLTHROUGH.values():
c += [' %s' % opcode.decode_clause]
c += [' %s' % opcode.decode_function]
else:
# This calls a decode function for v8.1 instructions which uses a new
# method of decoding.
c += [' return decode_v81(enc, dc, pc, instr);']
c.append('}')
return '\n'.join(c) + '\n'
# Call the next version of the decoder if defined.
if next_isa != '':
c.append(' return decoder_' + next_isa + '(enc, dc, pc, instr);')
Expand Down Expand Up @@ -297,6 +308,10 @@ def make_enc(n, reordered, f, opndtab):
def generate_opndset_encoders(opndsettab, opndtab):
c = []
for name in sorted(opndsettab):
# Ignore dummy codec_*.txt entries. This suppresses generation of this
# encoder function for instructions handled by the new encoder.
if name == 'gen_00000000_00000000':
return '\n'
os = opndsettab[name]
(fixed, dsts, srcs, enc_order) = (os.fixed, os.dsts, os.srcs, os.enc_order)
c += ['/* %s <- %s */' % (os.dsts, os.srcs)]
Expand Down Expand Up @@ -345,10 +360,17 @@ def generate_encoder(patterns, opndsettab, opndtab, curr_isa, next_isa):
case[mn].append(p)
c += ['static uint',
'encoder_' + curr_isa + '(byte *pc, instr_t *instr, decode_info_t *di)',
'{',
' uint enc;',
' (void)enc;',
' switch (instr->opcode) {']
'{']
# This calls an encode function for v8.1 instructions which uses a new
# method of encoding.
if curr_isa == 'v81':
c += [' return encode_v81(pc, instr, di);']
c.append('}')
return '\n'.join(c) + '\n'
else:
c += [' uint enc;',
' (void)enc;',
' switch (instr->opcode) {']

def reorder_key(t):
b, m, mn, f = t
Expand Down
15 changes: 5 additions & 10 deletions core/ir/aarch64/codec_v81.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,11 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.

# See header comments in codec_v80.txt and opnd_defs.txt to understand how
# instructions are defined for the purposes of decode and encode code
# generation.
# The new codec will no longer use the instruction specification format of
# codec_v80.txt and opnd_defs.txt to generate the decoder and encoder. This
# file is a temporary placeholder using dummy definitions to enable codec.py to
# ignore instructions handled by the new generator while it is in development.

# Instruction definitions:

0x1011111xxxxxxx1101x0xxxxxxxxxx n 412 sqrdmlah dq0 : dq5 dq16 vindex_SD sd_sz
0x10111101xxxxxx1101x0xxxxxxxxxx n 412 sqrdmlah dq0 : dq5 dq16_h_sz vindex_H h_sz
0111111101xxxxxx1101x0xxxxxxxxxx n 412 sqrdmlah h0 : h5 dq16_h_sz vindex_H h_sz
0111111110xxxxxx1101x0xxxxxxxxxx n 412 sqrdmlah s0 : s5 dq16 vindex_SD sd_sz
0x101110xx0xxxxx100001xxxxxxxxxx n 412 sqrdmlah dq0 : dq5 dq16 hs_sz
01111110010xxxxx100001xxxxxxxxxx n 412 sqrdmlah h0 : h5 h16
01111110100xxxxx100001xxxxxxxxxx n 412 sqrdmlah s0 : s5 s16
00000000000000000000000000000000 n 412 sqrdmlah :
Loading

0 comments on commit 4146c21

Please sign in to comment.