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 54/67] Hexagon - Add Hexagon Vector eXtensions (HVX) to core definition
Date: Fri, 28 Feb 2020 10:43:50 -0600 [thread overview]
Message-ID: <1582908244-304-55-git-send-email-tsimpson@quicinc.com> (raw)
In-Reply-To: <1582908244-304-1-git-send-email-tsimpson@quicinc.com>
HVX is a set of wide vector instructions. Machine state includes
vector registers (VRegs)
vector predicate registers (QRegs)
temporary registers for packet semantics
store buffer (masked stores and scatter/gather)
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
target/hexagon/cpu.h | 42 +++++++++++++++++++++
target/hexagon/insn.h | 16 ++++++++
target/hexagon/internal.h | 2 +
target/hexagon/mmvec/mmvec.h | 87 ++++++++++++++++++++++++++++++++++++++++++++
target/hexagon/cpu.c | 51 +++++++++++++++++++++++++-
5 files changed, 197 insertions(+), 1 deletion(-)
create mode 100644 target/hexagon/mmvec/mmvec.h
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 6146561..6215f91 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -30,6 +30,7 @@ typedef struct CPUHexagonState CPUHexagonState;
#include "qemu-common.h"
#include "exec/cpu-defs.h"
#include "hex_regs.h"
+#include "mmvec/mmvec.h"
#define NUM_PREGS 4
#ifdef CONFIG_USER_ONLY
@@ -42,6 +43,7 @@ typedef struct CPUHexagonState CPUHexagonState;
#define STORES_MAX 2
#define REG_WRITES_MAX 32
#define PRED_WRITES_MAX 5 /* 4 insns + endloop */
+#define VSTORES_MAX 2
#define TYPE_HEXAGON_CPU "hexagon-cpu"
@@ -60,6 +62,19 @@ struct MemLog {
uint64_t data64;
};
+typedef struct {
+ target_ulong va;
+ int size;
+ mmvector_t mask;
+ mmvector_t data;
+} vstorelog_t;
+
+typedef struct {
+ unsigned char cdata[256];
+ uint32_t range;
+ uint8_t format;
+} mem_access_info_t;
+
#define EXEC_STATUS_OK 0x0000
#define EXEC_STATUS_STOP 0x0002
#define EXEC_STATUS_REPLAY 0x0010
@@ -72,6 +87,9 @@ struct MemLog {
#define CLEAR_EXCEPTION (env->status &= (~EXEC_STATUS_EXCEPTION))
#define SET_EXCEPTION (env->status |= EXEC_STATUS_EXCEPTION)
+/* This needs to be large enough for all the reads and writes in a packet */
+#define TEMP_VECTORS_MAX 25
+
struct CPUHexagonState {
target_ulong gpr[TOTAL_PER_THREAD_REGS];
target_ulong pred[NUM_PREGS];
@@ -110,6 +128,30 @@ struct CPUHexagonState {
target_ulong is_gather_store_insn;
target_ulong gather_issued;
+
+ mmvector_t VRegs[NUM_VREGS];
+ mmvector_t future_VRegs[NUM_VREGS];
+ mmvector_t tmp_VRegs[NUM_VREGS];
+
+ VRegMask VRegs_updated_tmp;
+ VRegMask VRegs_updated;
+ VRegMask VRegs_select;
+
+ mmqreg_t QRegs[NUM_QREGS];
+ mmqreg_t future_QRegs[NUM_QREGS];
+ QRegMask QRegs_updated;
+
+ vstorelog_t vstore[VSTORES_MAX];
+ uint8_t store_pending[VSTORES_MAX];
+ uint8_t vstore_pending[VSTORES_MAX];
+ uint8_t vtcm_pending;
+ vtcm_storelog_t vtcm_log;
+ mem_access_info_t mem_access[SLOTS_MAX];
+
+ int status;
+
+ mmvector_t temp_vregs[TEMP_VECTORS_MAX];
+ mmqreg_t temp_qregs[TEMP_VECTORS_MAX];
};
#define HEXAGON_CPU_CLASS(klass) \
diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index a80bcb9..16d298d 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -49,12 +49,16 @@ struct Instruction {
size4u_t is_dcfetch:1; /* Has an A_DCFETCH attribute */
size4u_t is_load:1; /* Has A_LOAD attribute */
size4u_t is_store:1; /* Has A_STORE attribute */
+ size4u_t is_vmem_ld:1; /* Has an A_LOAD and an A_VMEM attribute */
+ size4u_t is_vmem_st:1; /* Has an A_STORE and an A_VMEM attribute */
+ size4u_t is_scatgath:1; /* Has an A_CVI_GATHER or A_CVI_SCATTER attr */
size4u_t is_memop:1; /* Has A_MEMOP attribute */
size4u_t is_dealloc:1; /* Is a dealloc return or dealloc frame */
size4u_t is_aia:1; /* Is a post increment */
size4u_t is_endloop:1; /* This is an end of loop */
size4u_t is_2nd_jump:1; /* This is the second jump of a dual-jump packet */
size4u_t new_value_producer_slot:4;
+ size4u_t hvx_resource:8;
size4s_t immed[IMMEDS_MAX]; /* immediate field */
};
@@ -121,10 +125,22 @@ struct Packet {
/* Misc */
size8u_t num_rops:4; /* Num risc ops in the packet */
+ size8u_t pkt_has_vtcm_access:1; /* Is a vmem access going to VTCM */
size8u_t pkt_access_count:2; /* Is a vmem access going to VTCM */
size8u_t pkt_ldaccess_l2:2; /* vmem ld access to l2 */
size8u_t pkt_ldaccess_vtcm:2; /* vmem ld access to vtcm */
+ /* Count the types of HVX instructions */
+ size8u_t pkt_hvx_va:4;
+ size8u_t pkt_hvx_vx:4;
+ size8u_t pkt_hvx_vp:4;
+ size8u_t pkt_hvx_vs:4;
+ size8u_t pkt_hvx_all:4;
+ size8u_t pkt_hvx_none:4;
+
+ size8u_t pkt_has_hvx:1;
+ size8u_t pkt_has_extension:1;
+
insn_t insn[INSTRUCTIONS_MAX];
};
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 092dedc..4ff7020 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -39,6 +39,8 @@
extern int hexagon_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
extern int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+extern void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
+extern void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
extern void hexagon_debug(CPUHexagonState *env);
#if COUNT_HEX_HELPERS
diff --git a/target/hexagon/mmvec/mmvec.h b/target/hexagon/mmvec/mmvec.h
new file mode 100644
index 0000000..145af15
--- /dev/null
+++ b/target/hexagon/mmvec/mmvec.h
@@ -0,0 +1,87 @@
+/*
+ * 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/>.
+ */
+
+#ifndef HEXAGON_MMVEC_H
+#define HEXAGON_MMVEC_H
+
+#define MAX_VEC_SIZE_LOGBYTES 7
+#define MAX_VEC_SIZE_BYTES (1 << MAX_VEC_SIZE_LOGBYTES)
+
+#define NUM_VREGS 32
+#define NUM_QREGS 4
+
+typedef uint32_t VRegMask; /* at least NUM_VREGS bits */
+typedef uint32_t QRegMask; /* at least NUM_QREGS bits */
+
+#define VECTOR_SIZE_BYTE (fVECSIZE())
+
+typedef union {
+ uint64_t ud[MAX_VEC_SIZE_BYTES / 8];
+ int64_t d[MAX_VEC_SIZE_BYTES / 8];
+ uint32_t uw[MAX_VEC_SIZE_BYTES / 4];
+ int32_t w[MAX_VEC_SIZE_BYTES / 4];
+ uint16_t uh[MAX_VEC_SIZE_BYTES / 2];
+ int16_t h[MAX_VEC_SIZE_BYTES / 2];
+ uint8_t ub[MAX_VEC_SIZE_BYTES / 1];
+ int8_t b[MAX_VEC_SIZE_BYTES / 1];
+} mmvector_t;
+
+typedef union {
+ uint64_t ud[2 * MAX_VEC_SIZE_BYTES / 8];
+ int64_t d[2 * MAX_VEC_SIZE_BYTES / 8];
+ uint32_t uw[2 * MAX_VEC_SIZE_BYTES / 4];
+ int32_t w[2 * MAX_VEC_SIZE_BYTES / 4];
+ uint16_t uh[2 * MAX_VEC_SIZE_BYTES / 2];
+ int16_t h[2 * MAX_VEC_SIZE_BYTES / 2];
+ uint8_t ub[2 * MAX_VEC_SIZE_BYTES / 1];
+ int8_t b[2 * MAX_VEC_SIZE_BYTES / 1];
+ mmvector_t v[2];
+} mmvector_pair_t;
+
+typedef union {
+ uint64_t ud[MAX_VEC_SIZE_BYTES / 8 / 8];
+ int64_t d[MAX_VEC_SIZE_BYTES / 8 / 8];
+ uint32_t uw[MAX_VEC_SIZE_BYTES / 4 / 8];
+ int32_t w[MAX_VEC_SIZE_BYTES / 4 / 8];
+ uint16_t uh[MAX_VEC_SIZE_BYTES / 2 / 8];
+ int16_t h[MAX_VEC_SIZE_BYTES / 2 / 8];
+ uint8_t ub[MAX_VEC_SIZE_BYTES / 1 / 8];
+ int8_t b[MAX_VEC_SIZE_BYTES / 1 / 8];
+} mmqreg_t;
+
+typedef struct {
+ mmvector_t data;
+ mmvector_t mask;
+ mmvector_pair_t offsets;
+ int size;
+ target_ulong va_base;
+ target_ulong va[MAX_VEC_SIZE_BYTES];
+ int oob_access;
+ int op;
+ int op_size;
+} vtcm_storelog_t;
+
+
+/* Types of vector register assignment */
+typedef enum {
+ EXT_DFL, /* Default */
+ EXT_NEW, /* New - value used in the same packet */
+ EXT_TMP /* Temp - value used but not stored to register */
+} vector_dst_type_t;
+
+#endif
+
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 576c566..ccbc113 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -122,6 +122,39 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
fprintf(f, " %s = 0x" TARGET_FMT_lx "\n", hexagon_regnames[regnum], value);
}
+static void print_vreg(FILE *f, CPUHexagonState *env, int regnum)
+{
+ int i;
+ fprintf(f, " v%d = (", regnum);
+ fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
+ for (i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
+ fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
+ }
+ fprintf(f, ")\n");
+}
+
+void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
+{
+ print_vreg(stdout, env, regnum);
+}
+
+static void print_qreg(FILE *f, CPUHexagonState *env, int regnum)
+{
+ int i;
+ fprintf(f, " q%d = (", regnum);
+ fprintf(f, ", 0x%02x",
+ env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
+ for (i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
+ fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
+ }
+ fprintf(f, ")\n");
+}
+
+void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
+{
+ print_qreg(stdout, env, regnum);
+}
+
static void hexagon_dump(CPUHexagonState *env, FILE *f)
{
static target_ulong last_pc;
@@ -166,6 +199,22 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f)
print_reg(f, env, HEX_REG_CS1);
#endif
fprintf(f, "}\n");
+
+/*
+ * The HVX register dump takes up a ton of space in the log
+ * Don't print it unless it is needed
+ */
+#define DUMP_HVX 0
+#if DUMP_HVX
+ fprintf(f, "Vector Registers = {\n");
+ for (i = 0; i < NUM_VREGS; i++) {
+ print_vreg(f, env, i);
+ }
+ for (i = 0; i < NUM_QREGS; i++) {
+ print_qreg(f, env, i);
+ }
+ fprintf(f, "}\n");
+#endif
}
static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
@@ -291,7 +340,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_core_xml_file = "hexagon-core.xml";
cc->gdb_read_register = hexagon_gdb_read_register;
cc->gdb_write_register = hexagon_gdb_write_register;
- cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
+ cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = hexagon_cpu_disas_set_info;
#ifdef CONFIG_TCG
--
2.7.4
next prev parent reply other threads:[~2020-02-28 17:37 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 ` Taylor Simpson [this message]
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-55-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).