From: Taylor Simpson <tsimpson@quicinc.com>
To: qemu-devel@nongnu.org
Cc: riku.voipio@iki.fi, richard.henderson@linaro.org,
laurent@vivier.eu, Taylor Simpson <tsimpson@quicinc.com>,
philmd@redhat.com, aleksandar.m.mail@gmail.com
Subject: [RFC PATCH v2 29/67] Hexagon generater phase 4 - Decode tree
Date: Fri, 28 Feb 2020 10:43:25 -0600 [thread overview]
Message-ID: <1582908244-304-30-git-send-email-tsimpson@quicinc.com> (raw)
In-Reply-To: <1582908244-304-1-git-send-email-tsimpson@quicinc.com>
Python script that emits the decode tree in dectree_generated.h.
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
target/hexagon/dectree.py | 353 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 353 insertions(+)
create mode 100755 target/hexagon/dectree.py
diff --git a/target/hexagon/dectree.py b/target/hexagon/dectree.py
new file mode 100755
index 0000000..2b9c82b
--- /dev/null
+++ b/target/hexagon/dectree.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python3
+
+##
+## Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved.
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+import io
+import re
+
+import sys
+sys.path.insert(0, sys.argv[1])
+import iset
+
+encs = {tag : ''.join(reversed(iset.iset[tag]['enc'].replace(' ', '')))
+ for tag in iset.tags if iset.iset[tag]['enc'] != 'MISSING ENCODING'}
+
+enc_classes = set([iset.iset[tag]['enc_class'] for tag in encs.keys()])
+subinsn_enc_classes = \
+ set([enc_class for enc_class in enc_classes \
+ if enc_class.startswith('SUBINSN_')])
+ext_enc_classes = \
+ set([enc_class for enc_class in enc_classes \
+ if enc_class not in ('NORMAL', '16BIT') and \
+ not enc_class.startswith('SUBINSN_')])
+
+try:
+ subinsn_groupings = iset.subinsn_groupings
+except AttributeError:
+ subinsn_groupings = {}
+
+for (tag, subinsn_grouping) in subinsn_groupings.items():
+ encs[tag] = ''.join(reversed(subinsn_grouping['enc'].replace(' ', '')))
+
+dectree_normal = {'leaves' : set()}
+dectree_16bit = {'leaves' : set()}
+dectree_subinsn_groupings = {'leaves' : set()}
+dectree_subinsns = {name : {'leaves' : set()} for name in subinsn_enc_classes}
+dectree_extensions = {name : {'leaves' : set()} for name in ext_enc_classes}
+
+for tag in encs.keys():
+ if tag in subinsn_groupings:
+ dectree_subinsn_groupings['leaves'].add(tag)
+ continue
+ enc_class = iset.iset[tag]['enc_class']
+ if enc_class.startswith('SUBINSN_'):
+ if len(encs[tag]) != 32:
+ encs[tag] = encs[tag] + '0' * (32 - len(encs[tag]))
+ dectree_subinsns[enc_class]['leaves'].add(tag)
+ elif enc_class == '16BIT':
+ if len(encs[tag]) != 16:
+ raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
+ 'width of 16 bits!'.format(tag, enc_class))
+ dectree_16bit['leaves'].add(tag)
+ else:
+ if len(encs[tag]) != 32:
+ raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
+ 'width of 32 bits!'.format(tag, enc_class))
+ if enc_class == 'NORMAL':
+ dectree_normal['leaves'].add(tag)
+ else:
+ dectree_extensions[enc_class]['leaves'].add(tag)
+
+faketags = set()
+for (tag, enc) in iset.enc_ext_spaces.items():
+ faketags.add(tag)
+ encs[tag] = ''.join(reversed(enc.replace(' ', '')))
+ dectree_normal['leaves'].add(tag)
+
+faketags |= set(subinsn_groupings.keys())
+
+def every_bit_counts(bitset):
+ for i in range(1, len(next(iter(bitset)))):
+ if len(set([bits[:i] + bits[i+1:] for bits in bitset])) == len(bitset):
+ return False
+ return True
+
+def auto_separate(node):
+ tags = node['leaves']
+ if len(tags) <= 1:
+ return
+ enc_width = len(encs[next(iter(tags))])
+ opcode_bit_for_all = \
+ [all([encs[tag][i] in '01' \
+ for tag in tags]) for i in range(enc_width)]
+ opcode_bit_is_0_for_all = \
+ [opcode_bit_for_all[i] and all([encs[tag][i] == '0' \
+ for tag in tags]) for i in range(enc_width)]
+ opcode_bit_is_1_for_all = \
+ [opcode_bit_for_all[i] and all([encs[tag][i] == '1' \
+ for tag in tags]) for i in range(enc_width)]
+ differentiator_opcode_bit = \
+ [opcode_bit_for_all[i] and \
+ not (opcode_bit_is_0_for_all[i] or \
+ opcode_bit_is_1_for_all[i]) \
+ for i in range(enc_width)]
+ best_width = 0
+ for width in range(4, 0, -1):
+ for lsb in range(enc_width - width, -1, -1):
+ bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
+ if all(differentiator_opcode_bit[lsb:lsb+width]) and \
+ (len(bitset) == len(tags) or every_bit_counts(bitset)):
+ best_width = width
+ best_lsb = lsb
+ caught_all_tags = len(bitset) == len(tags)
+ break
+ if best_width != 0:
+ break
+ if best_width == 0:
+ raise Exception('Could not find a way to differentiate the encodings ' +
+ 'of the following tags:\n{}'.format('\n'.join(tags)))
+ if caught_all_tags:
+ for width in range(1, best_width):
+ for lsb in range(enc_width - width, -1, -1):
+ bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
+ if all(differentiator_opcode_bit[lsb:lsb+width]) and \
+ len(bitset) == len(tags):
+ best_width = width
+ best_lsb = lsb
+ break
+ else:
+ continue
+ break
+ node['separator_lsb'] = best_lsb
+ node['separator_width'] = best_width
+ node['children'] = []
+ for value in range(2 ** best_width):
+ child = {}
+ bits = ''.join(reversed('{:0{}b}'.format(value, best_width)))
+ child['leaves'] = \
+ set([tag for tag in tags \
+ if encs[tag][best_lsb:best_lsb+best_width] == bits])
+ node['children'].append(child)
+ for child in node['children']:
+ auto_separate(child)
+
+auto_separate(dectree_normal)
+auto_separate(dectree_16bit)
+if subinsn_groupings:
+ auto_separate(dectree_subinsn_groupings)
+for dectree_subinsn in dectree_subinsns.values():
+ auto_separate(dectree_subinsn)
+for dectree_ext in dectree_extensions.values():
+ auto_separate(dectree_ext)
+
+for tag in faketags:
+ del encs[tag]
+
+def table_name(parents, node):
+ path = parents + [node]
+ root = path[0]
+ tag = next(iter(node['leaves']))
+ if tag in subinsn_groupings:
+ enc_width = len(subinsn_groupings[tag]['enc'].replace(' ', ''))
+ else:
+ tag = next(iter(node['leaves'] - faketags))
+ enc_width = len(encs[tag])
+ determining_bits = ['_'] * enc_width
+ for (parent, child) in zip(path[:-1], path[1:]):
+ lsb = parent['separator_lsb']
+ width = parent['separator_width']
+ value = parent['children'].index(child)
+ determining_bits[lsb:lsb+width] = \
+ list(reversed('{:0{}b}'.format(value, width)))
+ if tag in subinsn_groupings:
+ name = 'DECODE_ROOT_EE'
+ else:
+ enc_class = iset.iset[tag]['enc_class']
+ if enc_class in ext_enc_classes:
+ name = 'DECODE_EXT_{}'.format(enc_class)
+ elif enc_class in subinsn_enc_classes:
+ name = 'DECODE_SUBINSN_{}'.format(enc_class)
+ else:
+ name = 'DECODE_ROOT_{}'.format(enc_width)
+ if node != root:
+ name += '_' + ''.join(reversed(determining_bits))
+ return name
+
+def print_node(f, node, parents):
+ if len(node['leaves']) <= 1:
+ return
+ name = table_name(parents, node)
+ lsb = node['separator_lsb']
+ width = node['separator_width']
+ print('DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
+ format(name, 2 ** width, lsb, width), file=f)
+ for child in node['children']:
+ if len(child['leaves']) == 0:
+ print('INVALID()', file=f)
+ elif len(child['leaves']) == 1:
+ (tag,) = child['leaves']
+ if tag in subinsn_groupings:
+ class_a = subinsn_groupings[tag]['class_a']
+ class_b = subinsn_groupings[tag]['class_b']
+ enc = subinsn_groupings[tag]['enc'].replace(' ', '')
+ if 'RESERVED' in tag:
+ print('INVALID()', file=f)
+ else:
+ print('SUBINSNS({},{},{},"{}")'.\
+ format(tag, class_a, class_b, enc), file=f)
+ elif tag in iset.enc_ext_spaces:
+ enc = iset.enc_ext_spaces[tag].replace(' ', '')
+ print('EXTSPACE({},"{}")'.format(tag, enc), file=f)
+ else:
+ enc = ''.join(reversed(encs[tag]))
+ print('TERMINAL({},"{}")'.format(tag, enc), file=f)
+ else:
+ print('TABLE_LINK({})'.format(table_name(parents + [node], child)),
+ file=f)
+ print('DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
+ format(name, 2 ** width, lsb, width), file=f)
+ print(file=f)
+ parents.append(node)
+ for child in node['children']:
+ print_node(f, child, parents)
+ parents.pop()
+
+def print_tree(f, tree):
+ print_node(f, tree, [])
+
+def print_match_info(f):
+ for tag in sorted(encs.keys(), key=iset.tags.index):
+ enc = ''.join(reversed(encs[tag]))
+ mask = int(re.sub(r'[^1]', r'0', enc.replace('0', '1')), 2)
+ match = int(re.sub(r'[^01]', r'0', enc), 2)
+ suffix = ''
+ print('DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)'.\
+ format(suffix, tag, mask, match), file=f)
+
+regre = re.compile(
+ r'((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)')
+immre = re.compile(r'[#]([rRsSuUm])(\d+)(?:[:](\d+))?')
+
+def ordered_unique(l):
+ return sorted(set(l), key=l.index)
+
+implicit_registers = {
+ 'SP' : 29,
+ 'FP' : 30,
+ 'LR' : 31
+}
+
+num_registers = {
+ 'R' : 32,
+ 'V' : 32
+}
+
+def print_op_info(f):
+ for tag in sorted(encs.keys(), key=iset.tags.index):
+ enc = encs[tag]
+ print(file=f)
+ print('DECODE_OPINFO({},'.format(tag), file=f)
+ regs = ordered_unique(regre.findall(iset.iset[tag]['syntax']))
+ imms = ordered_unique(immre.findall(iset.iset[tag]['syntax']))
+ regno = 0
+ for reg in regs:
+ reg_type = reg[0]
+ reg_letter = reg[1][0]
+ reg_num_choices = int(reg[3].rstrip('S'))
+ reg_mapping = reg[0] + ''.join(['_' for letter in reg[1]]) + reg[3]
+ reg_enc_fields = re.findall(reg_letter + '+', enc)
+ if len(reg_enc_fields) == 0:
+ raise Exception('Tag "{}" missing register field!'.format(tag))
+ if len(reg_enc_fields) > 1:
+ raise Exception('Tag "{}" has split register field!'.\
+ format(tag))
+ reg_enc_field = reg_enc_fields[0]
+ if 2 ** len(reg_enc_field) != reg_num_choices:
+ raise Exception('Tag "{}" has incorrect register field width!'.\
+ format(tag))
+ print(' DECODE_REG({},{},{})'.\
+ format(regno, len(reg_enc_field), enc.index(reg_enc_field)),
+ file=f)
+ if reg_type in num_registers and \
+ reg_num_choices != num_registers[reg_type]:
+ print(' DECODE_MAPPED_REG({},{})'.\
+ format(regno, reg_mapping), file=f)
+ regno += 1
+ def implicit_register_key(reg):
+ return implicit_registers[reg]
+ for reg in sorted(
+ set([r for r in (iset.iset[tag]['rregs'].split(',') + \
+ iset.iset[tag]['wregs'].split(',')) \
+ if r in implicit_registers]), key=implicit_register_key):
+ print(' DECODE_IMPL_REG({},{})'.\
+ format(regno, implicit_registers[reg]), file=f)
+ regno += 1
+ if imms and imms[0][0].isupper():
+ imms = reversed(imms)
+ for imm in imms:
+ if imm[0].isupper():
+ immno = 1
+ else:
+ immno = 0
+ imm_type = imm[0]
+ imm_width = int(imm[1])
+ imm_shift = imm[2]
+ if imm_shift:
+ imm_shift = int(imm_shift)
+ else:
+ imm_shift = 0
+ if imm_type.islower():
+ imm_letter = 'i'
+ else:
+ imm_letter = 'I'
+ remainder = imm_width
+ for m in reversed(list(re.finditer(imm_letter + '+', enc))):
+ remainder -= m.end() - m.start()
+ print(' DECODE_IMM({},{},{},{})'.\
+ format(immno, m.end() - m.start(), m.start(), remainder),
+ file=f)
+ if remainder != 0:
+ if imm[2]:
+ imm[2] = ':' + imm[2]
+ raise Exception('Tag "{}" has an incorrect number of ' + \
+ 'encoding bits for immediate "{}"'.\
+ format(tag, ''.join(imm)))
+ if imm_type.lower() in 'sr':
+ print(' DECODE_IMM_SXT({},{})'.\
+ format(immno, imm_width), file=f)
+ if imm_type.lower() == 'n':
+ print(' DECODE_IMM_NEG({},{})'.\
+ format(immno, imm_width), file=f)
+ if imm_shift:
+ print(' DECODE_IMM_SHIFT({},{})'.\
+ format(immno, imm_shift), file=f)
+ print(')', file=f)
+
+if __name__ == '__main__':
+ f = io.StringIO()
+ print_tree(f, dectree_normal)
+ print_tree(f, dectree_16bit)
+ if subinsn_groupings:
+ print_tree(f, dectree_subinsn_groupings)
+ for (name, dectree_subinsn) in sorted(dectree_subinsns.items()):
+ print_tree(f, dectree_subinsn)
+ for (name, dectree_ext) in sorted(dectree_extensions.items()):
+ print_tree(f, dectree_ext)
+ print_match_info(f)
+ print_op_info(f)
+ open('dectree_generated.h', 'w').write(f.getvalue())
--
2.7.4
next prev parent reply other threads:[~2020-02-28 17:03 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-28 16:42 [RFC PATCH v2 00/67] Hexagon patch series Taylor Simpson
2020-02-28 16:42 ` [RFC PATCH v2 01/67] Hexagon Maintainers Taylor Simpson
2020-02-28 16:42 ` [RFC PATCH v2 02/67] Hexagon README Taylor Simpson
2020-02-28 16:42 ` [RFC PATCH v2 03/67] Hexagon ELF Machine Definition Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 04/67] Hexagon CPU Scalar Core Definition Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 05/67] Hexagon register names Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 06/67] Hexagon Disassembler Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 07/67] Hexagon CPU Scalar Core Helpers Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 08/67] Hexagon GDB Stub Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 09/67] Hexagon architecture types Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 10/67] Hexagon instruction and packet types Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 11/67] Hexagon register fields Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 12/67] Hexagon instruction attributes Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 13/67] Hexagon register map Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 14/67] Hexagon instruction/packet decode Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 15/67] Hexagon instruction printing Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 16/67] Hexagon arch import - instruction semantics definitions Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 17/67] Hexagon arch import - macro definitions Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 18/67] Hexagon arch import - instruction encoding Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 19/67] Hexagon instruction class definitions Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 20/67] Hexagon instruction utility functions Taylor Simpson
2020-04-09 18:53 ` Brian Cain
2020-04-09 20:22 ` Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 21/67] Hexagon generator phase 1 - C preprocessor for semantics Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 22/67] Hexagon generator phase 2 - qemu_def_generated.h Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 23/67] Hexagon generator phase 2 - qemu_wrap_generated.h Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 24/67] Hexagon generator phase 2 - opcodes_def_generated.h Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 25/67] Hexagon generator phase 2 - op_attribs_generated.h Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 26/67] Hexagon generator phase 2 - op_regs_generated.h Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 27/67] Hexagon generator phase 2 - printinsn-generated.h Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 28/67] Hexagon generator phase 3 - C preprocessor for decode tree Taylor Simpson
2020-02-28 16:43 ` Taylor Simpson [this message]
2020-02-28 16:43 ` [RFC PATCH v2 30/67] Hexagon opcode data structures Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 31/67] Hexagon macros to interface with the generator Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 32/67] Hexagon macros referenced in instruction semantics Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 33/67] Hexagon instruction classes Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 34/67] Hexagon TCG generation helpers - step 1 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 35/67] Hexagon TCG generation helpers - step 2 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 36/67] Hexagon TCG generation helpers - step 3 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 37/67] Hexagon TCG generation helpers - step 4 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 38/67] Hexagon TCG generation helpers - step 5 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 39/67] Hexagon TCG generation - step 01 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 40/67] Hexagon TCG generation - step 02 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 41/67] Hexagon TCG generation - step 03 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 42/67] Hexagon TCG generation - step 04 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 43/67] Hexagon TCG generation - step 05 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 44/67] Hexagon TCG generation - step 06 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 45/67] Hexagon TCG generation - step 07 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 46/67] Hexagon TCG generation - step 08 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 47/67] Hexagon TCG generation - step 09 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 48/67] Hexagon TCG generation - step 10 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 49/67] Hexagon TCG generation - step 11 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 50/67] Hexagon TCG generation - step 12 Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 51/67] Hexagon translation Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 52/67] Hexagon Linux user emulation Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 53/67] Hexagon build infrastructure Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 54/67] Hexagon - Add Hexagon Vector eXtensions (HVX) to core definition Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 55/67] Hexagon HVX support in gdbstub Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 56/67] Hexagon HVX import instruction encodings Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 57/67] Hexagon HVX import semantics Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 58/67] Hexagon HVX import macro definitions Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 59/67] Hexagon HVX semantics generator Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 60/67] Hexagon HVX instruction decoding Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 61/67] Hexagon HVX instruction utility functions Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 62/67] Hexagon HVX macros to interface with the generator Taylor Simpson
2020-02-28 16:43 ` [RFC PATCH v2 63/67] Hexagon HVX macros referenced in instruction semantics Taylor Simpson
2020-02-28 16:44 ` [RFC PATCH v2 64/67] Hexagon HVX helper to commit vector stores (masked and scatter/gather) Taylor Simpson
2020-02-28 16:44 ` [RFC PATCH v2 65/67] Hexagon HVX TCG generation Taylor Simpson
2020-02-28 16:44 ` [RFC PATCH v2 66/67] Hexagon HVX translation Taylor Simpson
2020-02-28 16:44 ` [RFC PATCH v2 67/67] Hexagon HVX build infrastructure Taylor Simpson
2020-03-25 21:13 ` [RFC PATCH v2 00/67] Hexagon patch series Taylor Simpson
2020-04-30 20:53 ` Taylor Simpson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1582908244-304-30-git-send-email-tsimpson@quicinc.com \
--to=tsimpson@quicinc.com \
--cc=aleksandar.m.mail@gmail.com \
--cc=laurent@vivier.eu \
--cc=philmd@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=riku.voipio@iki.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).