qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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 59/67] Hexagon HVX semantics generator
Date: Fri, 28 Feb 2020 10:43:55 -0600	[thread overview]
Message-ID: <1582908244-304-60-git-send-email-tsimpson@quicinc.com> (raw)
In-Reply-To: <1582908244-304-1-git-send-email-tsimpson@quicinc.com>

Add HVX support to the semantics generator

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
 target/hexagon/gen_semantics.c |   9 +++
 target/hexagon/do_qemu.py      | 175 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 171 insertions(+), 13 deletions(-)

diff --git a/target/hexagon/gen_semantics.c b/target/hexagon/gen_semantics.c
index 65d04fa..f5ee3ae 100644
--- a/target/hexagon/gen_semantics.c
+++ b/target/hexagon/gen_semantics.c
@@ -87,6 +87,15 @@ int main(int argc, char *argv[])
 #include "imported/macros.def"
 #undef DEF_MACRO
 
+/*
+ * Process the macros for HVX
+ */
+#define DEF_MACRO(MNAME, PARAMS, SDESC, LDESC, BEH, ATTRS) \
+    fprintf(outfile, "MACROATTRIB(\"%s\",\"\"\"%s\"\"\",\"%s\",\"%s\")\n", \
+            #MNAME, STRINGIZE(BEH), STRINGIZE(ATTRS), EXTSTR);
+#include "imported/allext_macros.def"
+#undef DEF_MACRO
+
     fclose(outfile);
     return 0;
 }
diff --git a/target/hexagon/do_qemu.py b/target/hexagon/do_qemu.py
index 32543c8..1306e6e 100755
--- a/target/hexagon/do_qemu.py
+++ b/target/hexagon/do_qemu.py
@@ -107,6 +107,16 @@ def SEMANTICS(tag, beh, sem):
     attribdict[tag] = set()
     tags.append(tag)        # dicts have no order, this is for order
 
+def EXT_SEMANTICS(ext, tag, beh, sem):
+    #print tag,beh,sem
+    extnames[ext] = True
+    extdict[tag] = ext
+    behdict[tag] = beh
+    semdict[tag] = sem
+    attribdict[tag] = set()
+    tags.append(tag)        # dicts have no order, this is for order
+
+
 def ATTRIBUTES(tag, attribstring):
     attribstring = \
         attribstring.replace("ATTRIBS","").replace("(","").replace(")","")
@@ -170,6 +180,9 @@ def compute_tag_immediates(tag):
 ##          P                predicate register
 ##          R                GPR register
 ##          M                modifier register
+##          Q                HVX predicate vector
+##          V                HVX vector register
+##          O                HVX new vector register
 ##      regid can be one of the following
 ##          d, e             destination register
 ##          dd               destination register pair
@@ -201,6 +214,9 @@ def is_readwrite(regid):
 def is_scalar_reg(regtype):
     return regtype in "RPC"
 
+def is_hvx_reg(regtype):
+    return regtype in "VQ"
+
 def is_old_val(regtype, regid, tag):
     return regtype+regid+'V' in semdict[tag]
 
@@ -211,7 +227,8 @@ tagimms = dict(zip(tags, list(map(compute_tag_immediates, tags))))
 
 def need_slot(tag):
     if ('A_CONDEXEC' in attribdict[tag] or
-        'A_STORE' in attribdict[tag]):
+        'A_STORE' in attribdict[tag] or
+        'A_CVI' in attribdict[tag]):
         return 1
     else:
         return 0
@@ -297,19 +314,32 @@ def gen_helper_prototype(f, tag, regs, imms):
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
 
         ## Generate the qemu DEF_HELPER type for each result
+        ## Iterate over this list twice
+        ## - Emit the scalar result
+        ## - Emit the vector result
         i=0
         for regtype,regid,toss,numregs in regs:
             if (is_written(regid)):
-                gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
+                if (not is_hvx_reg(regtype)):
+                    gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
                 i += 1
 
         ## Put the env between the outputs and inputs
         f.write(', env' )
         i += 1
 
+        # Second pass
+        for regtype,regid,toss,numregs in regs:
+            if (is_written(regid)):
+                if (is_hvx_reg(regtype)):
+                    gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
+                    i += 1
+
         ## Generate the qemu type for each input operand (regs and immediates)
         for regtype,regid,toss,numregs in regs:
             if (is_read(regid)):
+                if (is_hvx_reg(regtype) and is_readwrite(regid)):
+                    continue
                 gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
                 i += 1
         for immlett,bits,immshift in imms:
@@ -437,11 +467,33 @@ def genptr_dst_write(f,regtype, regid):
     macro = "WRITE_%sREG_%s" % (regtype, regid)
     f.write("%s(%s%sN, %s%sV);\n" % (macro, regtype, regid, regtype, regid))
 
+def genptr_dst_write_ext(f, regtype, regid, newv="0"):
+    macro = "WRITE_%sREG_%s" % (regtype, regid)
+    f.write("%s(%s%sN, %s%sV,%s);\n" % \
+            (macro, regtype, regid, regtype, regid, newv))
+
 def genptr_dst_write_opn(f,regtype, regid, tag):
     if (is_pair(regid)):
-        genptr_dst_write(f, regtype, regid)
+        if (is_hvx_reg(regtype)):
+            if ('A_CVI_TMP' in attribdict[tag] or
+                'A_CVI_TMP_DST' in attribdict[tag]):
+                genptr_dst_write_ext(f, regtype, regid, "EXT_TMP")
+            else:
+                genptr_dst_write_ext(f, regtype, regid)
+        else:
+            genptr_dst_write(f, regtype, regid)
     elif (is_single(regid)):
-        genptr_dst_write(f, regtype, regid)
+        if (is_hvx_reg(regtype)):
+            if 'A_CVI_NEW' in attribdict[tag]:
+                genptr_dst_write_ext(f, regtype, regid, "EXT_NEW")
+            elif 'A_CVI_TMP' in attribdict[tag]:
+                genptr_dst_write_ext(f, regtype, regid, "EXT_TMP")
+            elif 'A_CVI_TMP_DST' in attribdict[tag]:
+                genptr_dst_write_ext(f, regtype, regid, "EXT_TMP")
+            else:
+                genptr_dst_write_ext(f, regtype, regid, "EXT_DFL")
+        else:
+            genptr_dst_write(f, regtype, regid)
     else:
         print("Bad register parse: ",regtype,regid,toss,numregs)
 
@@ -504,13 +556,23 @@ def gen_tcg_func(f, tag, regs, imms):
     ## If there is a scalar result, it is the return type
     for regtype,regid,toss,numregs in regs:
         if (is_written(regid)):
+            if (is_hvx_reg(regtype)):
+                continue
             gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
             i += 1
     if (i > 0): f.write(", ")
     f.write("cpu_env")
     i=1
     for regtype,regid,toss,numregs in regs:
+        if (is_written(regid)):
+            if (not is_hvx_reg(regtype)):
+                continue
+            gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
+            i += 1
+    for regtype,regid,toss,numregs in regs:
         if (is_read(regid)):
+            if (is_hvx_reg(regtype) and is_readwrite(regid)):
+                continue
             gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
             i += 1
     for immlett,bits,immshift in imms:
@@ -573,12 +635,26 @@ def gen_helper_arg_pair(f,regtype,regid,regno):
     if regno >= 0 : f.write(", ")
     f.write("int64_t %s%sV" % (regtype,regid))
 
+def gen_helper_arg_ext(f,regtype,regid,regno):
+    if regno > 0 : f.write(", ")
+    f.write("void *%s%sV_void" % (regtype,regid))
+
+def gen_helper_arg_ext_pair(f,regtype,regid,regno):
+    if regno > 0 : f.write(", ")
+    f.write("void *%s%sV_void" % (regtype,regid))
+
 def gen_helper_arg_opn(f,regtype,regid,i):
     if (is_pair(regid)):
-        gen_helper_arg_pair(f,regtype,regid,i)
+        if (is_hvx_reg(regtype)):
+            gen_helper_arg_ext_pair(f,regtype,regid,i)
+        else:
+            gen_helper_arg_pair(f,regtype,regid,i)
     elif (is_single(regid)):
         if is_old_val(regtype, regid, tag):
-            gen_helper_arg(f,regtype,regid,i)
+            if (is_hvx_reg(regtype)):
+                gen_helper_arg_ext(f,regtype,regid,i)
+            else:
+                gen_helper_arg(f,regtype,regid,i)
         elif is_new_val(regtype, regid, tag):
             gen_helper_arg_new(f,regtype,regid,i)
         else:
@@ -597,25 +673,61 @@ def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""):
     f.write("int64_t %s%sV%s = 0;\n" % \
         (regtype,regid,subfield))
 
+def gen_helper_dest_decl_ext(f,regtype,regid):
+    f.write("/* %s%sV is *(mmvector_t*)(%s%sV_void) */\n" % \
+        (regtype,regid,regtype,regid))
+
+def gen_helper_dest_decl_ext_pair(f,regtype,regid,regno):
+    f.write("/* %s%sV is *(mmvector_pair_t*))%s%sV_void) */\n" % \
+        (regtype,regid,regtype, regid))
+
 def gen_helper_dest_decl_opn(f,regtype,regid,i):
     if (is_pair(regid)):
-        gen_helper_dest_decl_pair(f,regtype,regid,i)
+        if (is_hvx_reg(regtype)):
+            gen_helper_dest_decl_ext_pair(f,regtype,regid, i)
+        else:
+            gen_helper_dest_decl_pair(f,regtype,regid,i)
     elif (is_single(regid)):
-        gen_helper_dest_decl(f,regtype,regid,i)
+        if (is_hvx_reg(regtype)):
+            gen_helper_dest_decl_ext(f,regtype,regid)
+        else:
+            gen_helper_dest_decl(f,regtype,regid,i)
     else:
         print("Bad register parse: ",regtype,regid,toss,numregs)
 
+def gen_helper_src_var_ext(f,regtype,regid):
+    f.write("/* %s%sV is *(mmvector_t*)(%s%sV_void) */\n" % \
+        (regtype,regid,regtype,regid))
+
+def gen_helper_src_var_ext_pair(f,regtype,regid,regno):
+    f.write("/* %s%sV%s is *(mmvector_pair_t*)(%s%sV%s_void) */\n" % \
+        (regtype,regid,regno,regtype,regid,regno))
+
 def gen_helper_return(f,regtype,regid,regno):
     f.write("return %s%sV;\n" % (regtype,regid))
 
 def gen_helper_return_pair(f,regtype,regid,regno):
     f.write("return %s%sV;\n" % (regtype,regid))
 
+def gen_helper_dst_write_ext(f,regtype,regid):
+    f.write("/* %s%sV is *(mmvector_t*)%s%sV_void */\n" % \
+        (regtype,regid,regtype,regid))
+
+def gen_helper_dst_write_ext_pair(f,regtype,regid):
+    f.write("/* %s%sV is *(mmvector_pair_t*)%s%sV_void */\n" % \
+        (regtype,regid, regtype,regid))
+
 def gen_helper_return_opn(f, regtype, regid, i):
     if (is_pair(regid)):
-        gen_helper_return_pair(f,regtype,regid,i)
+        if (is_hvx_reg(regtype)):
+            gen_helper_dst_write_ext_pair(f,regtype,regid)
+        else:
+            gen_helper_return_pair(f,regtype,regid,i)
     elif (is_single(regid)):
-        gen_helper_return(f,regtype,regid,i)
+        if (is_hvx_reg(regtype)):
+            gen_helper_dst_write_ext(f,regtype,regid)
+        else:
+            gen_helper_return(f,regtype,regid,i)
     else:
         print("Bad register parse: ",regtype,regid,toss,numregs)
 
@@ -654,14 +766,20 @@ def gen_helper_definition(f, tag, regs, imms):
                 % (tag, tag))
     else:
         ## The return type of the function is the type of the destination
-        ## register
+        ## register (if scalar)
         i=0
         for regtype,regid,toss,numregs in regs:
             if (is_written(regid)):
                 if (is_pair(regid)):
-                    gen_helper_return_type_pair(f,regtype,regid,i)
+                    if (is_hvx_reg(regtype)):
+                        continue
+                    else:
+                        gen_helper_return_type_pair(f,regtype,regid,i)
                 elif (is_single(regid)):
-                    gen_helper_return_type(f,regtype,regid,i)
+                    if (is_hvx_reg(regtype)):
+                            continue
+                    else:
+                        gen_helper_return_type(f,regtype,regid,i)
                 else:
                     print("Bad register parse: ",regtype,regid,toss,numregs)
             i += 1
@@ -670,10 +788,30 @@ def gen_helper_definition(f, tag, regs, imms):
             f.write("void")
         f.write(" HELPER(%s)(CPUHexagonState *env" % tag)
 
+        ## Arguments include the vector destination operands
         i = 1
+        for regtype,regid,toss,numregs in regs:
+            if (is_written(regid)):
+                if (is_pair(regid)):
+                    if (is_hvx_reg(regtype)):
+                        gen_helper_arg_ext_pair(f,regtype,regid,i)
+                    else:
+                        continue
+                elif (is_single(regid)):
+                    if (is_hvx_reg(regtype)):
+                        gen_helper_arg_ext(f,regtype,regid,i)
+                    else:
+                        # This is the return value of the function
+                        continue
+                else:
+                    print("Bad register parse: ",regtype,regid,toss,numregs)
+                i += 1
+
         ## Arguments to the helper function are the source regs and immediates
         for regtype,regid,toss,numregs in regs:
             if (is_read(regid)):
+                if (is_hvx_reg(regtype) and is_readwrite(regid)):
+                    continue
                 gen_helper_arg_opn(f,regtype,regid,i)
                 i += 1
         for immlett,bits,immshift in imms:
@@ -696,6 +834,17 @@ def gen_helper_definition(f, tag, regs, imms):
                 gen_helper_dest_decl_opn(f,regtype,regid,i)
             i += 1
 
+        for regtype,regid,toss,numregs in regs:
+            if (is_read(regid)):
+                if (is_pair(regid)):
+                    if (is_hvx_reg(regtype)):
+                        gen_helper_src_var_ext_pair(f,regtype,regid,i)
+                elif (is_single(regid)):
+                    if (is_hvx_reg(regtype)):
+                        gen_helper_src_var_ext(f,regtype,regid)
+                else:
+                    print("Bad register parse: ",regtype,regid,toss,numregs)
+
         if 'A_FPOP' in attribdict[tag]:
             f.write('fFPOP_START();\n');
 
-- 
2.7.4


  parent reply	other threads:[~2020-02-28 17:23 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 ` [RFC PATCH v2 29/67] Hexagon generater phase 4 - Decode tree Taylor Simpson
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 ` Taylor Simpson [this message]
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-60-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).